26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
53 #pragma package(smart_init)
72 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
73 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
74 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
75 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
76 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
77 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
88 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
89 AnsiString(TrainModeIn));
136 for(
int x = 0; x < 4; x++)
145 for(
int x = 0; x < 4; x++)
154 for(
int x = 0; x < 4; x++)
159 for(
int x = 0; x < 4; x++)
163 for(
int x = 0; x < 3; x++)
201 for(
int x = 0; x < 4; x++)
260 throw Exception(
"Error in attempting to delete FrontCodePtr");
264 for(
int x = 0; x < 4; x++)
268 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
273 for(
int x = 0; x < 4; x++)
277 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
306 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
372 bool TempDerail =
false;
418 else if((NextElementPosition > -1) && (NextEntryPos > -1))
489 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
499 for(
int x = 0; x < 4; x++)
506 for(
int x = 0; x < 4; x++)
767 int LockedVectorNumber;
897 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
898 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
899 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
900 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
901 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
902 "of a shortage of on train crew"};
909 if(DwellTime < TDateTime(30.0 / 86400))
911 DwellTime = TDateTime(30.0 / 86400);
913 int randval = random(10000);
918 if(randval < Utilities->MinorDelayCutoff)
925 if(randval < Utilities->ModerateDelayCutoff)
932 if(randval < Utilities->MajorDelayCutoff)
947 if(
NewDelay <
double(DwellTime) * 1440)
953 NewDelay -= double(DwellTime) * 1440;
1014 int randval2 = rand() % 24;
1015 AnsiString Reason = ReasonArray[randval2];
1018 " minutes because " + Reason);
1020 " minutes because " + Reason);
1026 " minutes because of a minor problem");
1028 " minutes because of a minor problem");
1180 if(BufferLocation ==
"")
1185 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1247 int NextElementPosition, NextEntryPos;
1271 NextElementPosition = -1;
1274 if((NextElementPosition > -1) && (NextEntryPos > -1))
1411 AnsiString StationName;
1422 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1436 if((NextElementPosition > -1) && (NextEntryPos > -1))
1570 if(TIFEntryPos == 0)
1607 if(NextElementPosition > -1)
1644 AnsiString Loc =
"";
1645 bool LocNamed =
false;
1674 Loc =
"outside railway";
1706 NextElementPosition = -1;
1717 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1735 if((NextElementPosition > -1) && (NextEntryPos > -1))
1773 FirstPair.second).
GetELink() == TempELink))
1778 SecondPair.second).
GetELink() == TempELink))
1792 FirstPair.second).
GetELink() == TempELink))
1797 SecondPair.second).
GetELink() == TempELink))
1811 FirstPair.second).
GetELink() == TempELink))
1816 SecondPair.second).
GetELink() == TempELink))
1846 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1849 int NewLastElement = 0, NewLastExitPos = 0;
1867 if(NewLastElement == -1)
1873 if(NewLastExitPos == -1)
1877 LastElement = NewLastElement;
1878 LastExitPos = NewLastExitPos;
1881 if(CumDistance < 1200)
1887 int FirstDistance = 0;
1888 if(CumDistance >= 1200)
1890 FirstDistance = 100;
1894 FirstDistance = 1200 - CumDistance;
1896 if(FirstDistance < 100)
1898 FirstDistance = 100;
1924 if(VectorIT->RouteNumber == RouteNumber)
1961 " failed when changing aspect.\nTrains can only pass under signaller control.");
1995 LockedVectorNumber)))
2154 for(
int x = 0; x < 4; x++)
2161 for(
int x = 0; x < 4; x++)
2187 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2192 if(OtherTrainEntryPos == -1)
2194 throw Exception(
"Error - OtherTrainEntryPos not set");
2213 int OtherTrainID = -1;
2214 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2305 bool StopRequired =
false;
2320 int NextElementEntryPos = -1;
2321 int NextElementExitPos = -1;
2322 bool TrainOnNextElement =
false;
2323 bool StopSignalAtNextElement =
false;
2324 if(ForwardConnection)
2332 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2334 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || TrainAtStopLinkPos3 || TrainAtStopLinkPos4 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2390 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2603 if(Code.Length() != 4)
2607 for(
int x = 1; x < 5; x++)
2614 for(
int x = 0; x < 4; x++)
2777 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2790 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2805 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2814 TRect SourceRect, DestRect;
2816 DestRect.init(0, 0, 8, 8);
2819 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2821 TempGraphic->PixelFormat = pf8bit;
2822 TempGraphic->Width = 16;
2823 TempGraphic->Height = 16;
2829 TempGraphic->Transparent =
true;
2833 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2834 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2840 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2848 else if(TempElement.
SpeedTag == 89)
2852 else if(TempElement.
SpeedTag == 90)
2856 else if(TempElement.
SpeedTag == 91)
2860 else if(TempElement.
SpeedTag == 92)
2864 else if(TempElement.
SpeedTag == 93)
2868 else if(TempElement.
SpeedTag == 94)
2872 else if(TempElement.
SpeedTag == 95)
2876 TempGraphic->Transparent =
true;
2880 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2881 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2883 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2890 for(
int x = 0; x < 40; x++)
2905 TempGraphic->Transparent =
true;
2909 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2910 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2912 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2926 TempGraphic->Transparent =
true;
2930 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2931 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2935 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2938 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2943 TempGraphic->Transparent =
true;
2947 int BDVectorPos = -1;
2956 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2961 TempGraphic->Transparent =
true;
2965 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2966 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2968 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2974 TempGraphic->Transparent =
true;
2978 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2979 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2981 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3247 throw Exception(
"Error, same train on two different bridge tracks");
3293 AnsiString(EntryPos) +
"," +
HeadCode);
3310 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3329 AnsiString(EntryPos) +
"," +
HeadCode);
3338 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3371 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3372 int LockedVectorNumber;
3385 TRect SourceRect, DestRect;
3386 DestRect.init(0, 0, 8, 8);
3393 int FirstELink, SecondELink = -1;
3396 if(RoutePair2.first > -1)
3405 if(SecondELink == -1)
3407 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3412 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3422 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3423 DestGraphic->PixelFormat = pf8bit;
3424 DestGraphic->Width = 8;
3425 DestGraphic->Height = 8;
3426 DestGraphic->Transparent =
true;
3429 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3438 PrefDirElement, LockedVectorNumber))
3453 if(ElementEntryPos > 1)
3475 AnsiString(EntryPos) +
"," +
HeadCode);
3477 bool WrongRoute =
false;
3503 int LinkNumber = TrackElement.
Link[EntryPos];
3504 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3509 bool LogActionErrorCalled =
false;
3519 LogActionErrorCalled =
true;
3536 else if(LinkNumber == 3)
3544 LogActionErrorCalled =
true;
3561 else if(LinkNumber == 7)
3569 LogActionErrorCalled =
true;
3586 else if(LinkNumber == 9)
3594 LogActionErrorCalled =
true;
3626 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3631 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3641 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3646 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3655 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3676 bool ColourError =
false, ColourError2 =
false;
3681 ColourError2 =
true;
3683 for(
int x = 0; x < 4; x++)
3688 ColourError2 =
true;
3694 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3698 for(
int x = 0; x < 4; x++)
3785 AnsiString(EntryPos) +
"," +
HeadCode);
3786 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3787 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3788 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3789 TrainInFrontInSignallerModeFlag =
false;
3790 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3791 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3792 bool SignallerStopRequired =
false;
3806 if(CurrentTrackVectorPosition > -1)
3810 if((EntryPos == 0) || (EntryPos == 2))
3823 else if(EntryPos == 1)
3847 EntryHalfLength = CurrentElementHalfLength;
3852 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3856 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3904 FrontElementMaxSpeed = LimitingSpeed;
3940 double ExitSpeedAtMaxBraking;
3945 ExitSpeedAtMaxBraking = 0;
3955 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3957 SpeedToUse = ExitSpeedAtMaxBraking;
3961 SpeedToUse = LimitingSpeed;
3976 RedSignalFlag =
false;
3977 BuffersFlag =
false;
3978 StationFlag =
false;
3979 BuffersOrContinuationNowFlag =
false;
3980 ContinuationNextFlag =
false;
3983 CumulativeLength += (2 * CurrentElementHalfLength);
3986 SignallerStopRequired =
true;
4008 bool StopRequired =
false;
4024 StationFlag =
false;
4030 BuffersOrContinuationNowFlag =
true;
4032 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
4036 if((EntryPos == 0) || (EntryPos == 2))
4058 if(NextTrackVectorPosition > -1)
4063 if((NextEntryPos == 0) || (NextEntryPos == 2))
4076 else if(NextEntryPos == 1)
4089 if(NextEntryPos > 1)
4103 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4115 RedSignalFlag =
true;
4136 TrainInFrontInSignallerModeFlag =
true;
4161 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4173 double MaxHalfSpeed;
4177 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4179 MaxHalfSpeed = FrontElementMaxSpeed;
4183 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4191 bool HalfSpeedLimited =
false;
4195 HalfSpeedLimited =
true;
4225 if(HalfSpeedLimited)
4250 if(SignallerStopRequired)
4266 int TempMaxExitSpeed;
4269 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4271 MaxExitSpeedAtHalfBraking = 0;
4275 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4279 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4281 TempMaxExitSpeed = FrontElementMaxSpeed;
4285 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4297 if(ExitSpeedHalfSquared < 10)
4307 if(ExitSpeedFullSquared < 10)
4379 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4380 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4404 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4405 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4415 if(!BuffersOrContinuationNowFlag)
4417 if(NextSpeedLimit < LimitingSpeed)
4419 LimitingSpeed = NextSpeedLimit;
4423 int TempMaxExitSpeed;
4427 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4429 MaxExitSpeedAtHalfBraking = 0;
4433 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4435 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4437 TempMaxExitSpeed = FrontElementMaxSpeed;
4441 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4452 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4465 if(!BuffersOrContinuationNowFlag)
4467 CurrentTrackVectorPosition = NextTrackVectorPosition;
4468 EntryPos = NextEntryPos;
4469 CurrentElementHalfLength = NextElementHalfLength;
4472 ContinuationNextFlag =
true;
4476 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4496 if(ExitSpeedHalfSquared < 10)
4506 if(ExitSpeedFullSquared < 10)
4569 double DeltaExitTimeToMaxInSecs;
4570 double DistanceToMax;
4579 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4581 DistanceToMax = EntryHalfLength;
4584 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4585 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4602 double DeltaExitTimeToMaxInSecs;
4603 double DistanceToMax;
4612 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4614 DistanceToMax = EntryHalfLength / 2;
4617 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4618 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4629 if(ExitSpeedHalfSquared < 10)
4639 if(ExitSpeedFullSquared < 10)
4658 if((EntryPos == 0) || (EntryPos == 2))
4680 if(NextTrackVectorPosition > -1)
4682 int NextElementLength;
4683 if(NextEntryPos > 1)
4691 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4887 int ElementCount = 0;
4895 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4953 if((EntryPos == 0) || (EntryPos == 2))
4975 CurrentTrackVectorPosition = NextTrackVectorPosition;
4976 EntryPos = NextEntryPos;
4978 if(ElementCount > 1000)
5006 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
5031 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
5032 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
5033 int RouteStartPosition;
5035 int PlatformPosition;
5037 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
5053 if(Distance > (4000 + LeadElementDistance))
5076 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5079 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5125 if(!PlatformFoundFlag)
5127 PlatformPosition = CurrentTrackVectorPosition;
5130 PlatformFoundFlag =
true;
5146 if((EntryPos == 0) || (EntryPos == 2))
5190 if(ElementNumber < 2)
5192 SkipRouteCheck =
true;
5196 SkipRouteCheck =
false;
5198 if(ElementNumber == 1)
5200 RouteStartPosition = CurrentTrackVectorPosition;
5210 if(ElementNumber > 1)
5214 RouteOrPartRouteSet =
true;
5218 RouteOrPartRouteSet =
false;
5221 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5228 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5229 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5241 Distance += CurrentTrackElement.
Length01;
5245 Distance += CurrentTrackElement.
Length23;
5247 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5248 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5249 CurrentTrackVectorPosition = NextTrackVectorPosition;
5250 EntryPos = NextEntryPos;
5287 return(RepeatHeadCode);
5309 bool FrontValid =
false, RearValid =
false;
5310 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5314 TrainToBeJoinedBy = NULL;
5328 int TrainToBeJoinedByID = -1;
5349 if((TrainToBeJoinedByID < 0) && RearValid)
5368 if(TrainToBeJoinedByID < 0)
5370 TrainToBeJoinedBy = NULL;
5375 if(!TrainToBeJoinedBy->
Stopped())
5377 TrainToBeJoinedBy = NULL;
5387 void TTrain::LogAction(
int Caller, AnsiString OwnHeadCode, AnsiString OtherHeadCode,
TActionType ActionType, AnsiString LocationName, AnsiString SplitDistribution,
5388 TDateTime TimetableNonRepeatTime,
bool Warning)
5424 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5425 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
5426 int IntMinsLate = 0;
5431 ActionLog =
" arrived at ";
5440 ActionLog =
" terminated at ";
5445 ActionLog =
" departed from ";
5447 if(ActionType ==
Pass)
5449 ActionLog =
" passed ";
5453 ActionLog =
" created at ";
5455 if(ActionType ==
Enter)
5457 ActionLog =
" entered railway at ";
5461 ActionLog =
" changed its description to '" +
Description +
"' at ";
5463 if(ActionType ==
Leave)
5465 ActionLog =
" left railway at ";
5469 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from front to ";
5473 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from rear to ";
5477 ActionLog =
" joined by ";
5481 ActionLog =
" changed direction at ";
5485 ActionLog =
" became new service ";
5489 ActionLog =
" taken under signaller control at ";
5493 ActionLog =
" restored to timetable control at ";
5499 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5503 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5507 ActionLog =
" REMOVED FROM RAILWAY at ";
5512 ActionLog =
" received signaller authority to proceed";
5516 ActionLog =
" received signaller authority to step forward";
5520 ActionLog =
" changed direction under signaller control at ";
5524 ActionLog =
" received signaller authority to pass stop signal";
5528 ActionLog =
" received signaller instruction to stop";
5532 ActionLog =
" stopped on signaller instruction ";
5536 ActionLog =
" joined under signaller control by ";
5540 ActionLog =
" suffered an onboard power failure at ";
5544 ActionLog =
" failure repaired at ";
5548 ActionLog =
" left railway under signaller control at ";
5550 if(OtherHeadCode !=
"")
5552 OtherHeadCode +=
" at ";
5565 bool TimePerformance =
true;
5573 TimePerformance =
false;
5577 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5579 if(ActionType ==
Pass)
5593 IntMinsLate = int(ceil(MinsLate));
5597 IntMinsLate = int(floor(MinsLate));
5599 if(IntMinsLate == 0)
5601 PerfLog =
" on time";
5603 else if(IntMinsLate == 1)
5605 PerfLog =
" 1 minute late";
5607 else if(IntMinsLate == -1)
5609 PerfLog =
" 1 minute early";
5611 else if(IntMinsLate > 1)
5613 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5615 else if(IntMinsLate < -1)
5617 int PosIntMinsLate = -IntMinsLate;
5618 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5620 if(LocationName.Pos(
'-') > 0)
5622 PerfLog =
"," + PerfLog;
5636 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5640 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5645 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5651 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5655 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5660 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5666 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5670 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5675 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5681 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5685 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5704 AnsiString LocName =
"";
5771 if(LocationName ==
"")
5775 int RearTrainRearPos, RearTrainFrontPos, RearTrainExitPos;
5776 int FrontTrainRearPos, FrontTrainFrontPos;
5779 if(LocationName ==
"")
5781 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5785 bool TemporaryDelay =
false;
5787 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
5811 AnsiString SplittingTrainDescription =
Description;
5818 for(
int x = 0; x < 4; x++)
5838 double NewTrainPowerAtRail;
5844 NewTrainMass =
Mass * double(MassPercent)/100.0;
5846 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
5847 if(NewTrainPowerAtRail == 0)
5849 NewTrainPowerAtRail = 0.08;
5857 NewTrainMass =
Mass;
5885 if(!SplitTrainExplicitDescription)
5927 if(LocationName ==
"")
5931 int RearTrainRearPos, RearTrainFrontPos;
5932 int FrontTrainRearPos, FrontTrainFrontPos, FrontTrainExitPos;
5935 if(LocationName ==
"")
5937 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5941 bool TemporaryDelay =
false;
5943 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
5967 AnsiString SplittingTrainDescription =
Description;
5974 for(
int x = 0; x < 4; x++)
5994 double NewTrainPowerAtRail;
6000 NewTrainMass =
Mass * double(MassPercent)/100.0;
6002 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6003 if(NewTrainPowerAtRail == 0)
6005 NewTrainPowerAtRail = 0.08;
6013 NewTrainMass =
Mass;
6041 if(!SplitTrainExplicitDescription)
6129 TTrain *TrainToBeJoinedBy;
6162 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6164 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6225 int RouteNumber = -1;
6230 int CorrectRouteID = OR.
RouteID;
6236 bool FirstPass =
true;
6241 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6355 for(
int x = 0; x < IncNum; x++)
6388 else if(Ptr->
Command ==
"jbo")
6393 else if(Ptr->
Command ==
"dsc")
6404 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6410 bool IncludeFER =
false;
6418 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6423 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6434 else if(Ptr->
Command ==
"Fjo")
6440 else if(Ptr->
Command ==
"Frh")
6450 else if(Ptr->
Command ==
"Frh-sh")
6501 else if(Ptr->
Command ==
"jbo")
6506 else if(Ptr->
Command ==
"dsc")
6511 else if(Ptr->
Command ==
"cdt")
6519 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6932 int RouteNumber = -1;
6937 int CorrectRouteID = OR.
RouteID;
6943 bool FirstPass =
true;
6948 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6976 ",FloatingLabelNextString" +
"," +
HeadCode);
6977 AnsiString RetStr =
"", LocationName =
"";
6980 if(ActionTime == TDateTime(-1))
6984 if(ActionTime == TDateTime(-1))
6990 if(ActionTime != TDateTime(-1))
6998 throw Exception(
"Error - start entry in FloatingLabelNextString");
7042 else if(Ptr->
Command ==
"Fns")
7048 else if(Ptr->
Command ==
"F-nshs")
7079 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7081 else if(Ptr->
Command ==
"Frh")
7083 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7085 else if(Ptr->
Command ==
"Fer")
7087 AnsiString AllowedExits =
"";
7090 else if(Ptr->
Command ==
"Fjo")
7095 else if(Ptr->
Command ==
"jbo")
7100 else if(Ptr->
Command ==
"fsp")
7105 else if(Ptr->
Command ==
"rsp")
7110 else if(Ptr->
Command ==
"cdt")
7114 else if(Ptr->
Command ==
"dsc")
7123 throw Exception(
"Error - start entry in FloatingLabelNextString where TTClockTime > ActionTime");
7167 else if(Ptr->
Command ==
"Fns")
7173 else if(Ptr->
Command ==
"F-nshs")
7204 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7206 else if(Ptr->
Command ==
"Frh")
7208 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7210 else if(Ptr->
Command ==
"Fer")
7212 AnsiString AllowedExits =
"";
7215 else if(Ptr->
Command ==
"Fjo")
7220 else if(Ptr->
Command ==
"jbo")
7225 else if(Ptr->
Command ==
"fsp")
7230 else if(Ptr->
Command ==
"rsp")
7235 else if(Ptr->
Command ==
"cdt")
7239 else if(Ptr->
Command ==
"dsc")
7248 throw Exception(
"Error - start entry in FloatingLabelNextString in final 'else'");
7292 else if(Ptr->
Command ==
"Fns")
7298 else if(Ptr->
Command ==
"F-nshs")
7329 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7331 else if(Ptr->
Command ==
"Frh")
7333 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7335 else if(Ptr->
Command ==
"Fer")
7337 AnsiString AllowedExits =
"";
7340 else if(Ptr->
Command ==
"Fjo")
7345 else if(Ptr->
Command ==
"jbo")
7350 else if(Ptr->
Command ==
"fsp")
7355 else if(Ptr->
Command ==
"rsp")
7360 else if(Ptr->
Command ==
"cdt")
7364 else if(Ptr->
Command ==
"dsc")
7508 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7509 AnsiString DepTime =
"", EventTime =
"";
7510 bool CDTFlag =
false;
7512 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7513 AnsiString TowardsLocation =
"";
7516 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7518 TowardsLocation = AVI->LocationName;
7520 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7529 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
7536 if(AVI->Command ==
"cdt")
7541 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7556 RetStr +=
"\nNew service splits at approx. " + EventTime;
7560 if(AVI->Command ==
"jbo")
7575 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at approx. " + EventTime;
7579 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
7594 RetStr +=
"\nNew service finishes and forms another new service at approx. " + EventTime;
7598 if(AVI->Command ==
"Fjo")
7613 RetStr +=
"\nNew service finishes and joins " + AVI->OtherHeadCode +
" at approx. " + EventTime;
7617 if(AVI->Command ==
"Frh")
7619 RetStr +=
"\nNew service finishes and remains at the location.";
7623 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7630 if(TowardsLocation !=
"")
7632 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
7636 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7641 if(TowardsLocation !=
"")
7643 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
7647 RetStr +=
"\nNew service departs at " + DepTime;
7656 if(TowardsLocation !=
"")
7658 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7662 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7667 if(TowardsLocation !=
"")
7669 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7673 RetStr +=
"\nNew service departs at approx. " + DepTime;
7690 if(TowardsLocation !=
"")
7692 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7696 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7701 if(TowardsLocation !=
"")
7703 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7707 RetStr +=
"\nNew service departs at approx. " + DepTime;
7726 ",FloatingTimetableString" +
"," +
HeadCode);
7727 AnsiString RetStr =
"", PartStr =
"";
7729 bool SkipDep =
false, SkipDepActedOn =
false;
7735 throw Exception(
"Error - start entry in FloatingTimetableString");
7738 bool FirstPass =
true;
7751 AnsiString TrainLoc =
"";
7797 AnsiString TrainLoc =
"";
7837 else if(Ptr->
Command ==
"Fns")
7843 else if(Ptr->
Command ==
"F-nshs")
7876 else if(Ptr->
Command ==
"Frh")
7880 else if(Ptr->
Command ==
"Fer")
7882 AnsiString AllowedExits =
"";
7885 else if(Ptr->
Command ==
"Fjo")
7890 else if(Ptr->
Command ==
"jbo")
7895 else if(Ptr->
Command ==
"fsp")
7905 PartStr+=
", split mass%-Power% = 50-50";
7908 else if(Ptr->
Command ==
"rsp")
7918 PartStr+=
", split mass%-Power% = 50-50";
7921 else if(Ptr->
Command ==
"cdt")
7925 else if(Ptr->
Command ==
"dsc")
7931 RetStr = RetStr +
'\n' + PartStr;
7945 SkipDepActedOn =
true;
7956 RetStr =
"Timetable finished";
7960 RetStr =
"No timetable";
7964 return(
"Timetable:\n" + RetStr);
8117 bool ForwardHeadCode;
8121 ForwardHeadCode =
true;
8126 ForwardHeadCode =
false;
8269 if(ColourNumber == 0)
8273 else if(ColourNumber == 1)
8277 else if(ColourNumber == 2)
8281 else if(ColourNumber == 3)
8285 else if(ColourNumber == 4)
8289 else if(ColourNumber == 5)
8293 else if(ColourNumber == 6)
8297 else if(ColourNumber == 7)
8301 else if(ColourNumber == 8)
8305 else if(ColourNumber == 9)
8309 else if(ColourNumber == 10)
8313 else if(ColourNumber == 11)
8317 else if(ColourNumber == 12)
8321 else if(ColourNumber == 13)
8325 else if(ColourNumber == 14)
8337 for(
int x = 0; x < 4; x++)
8344 for(
int x = 0; x < 4; x++)
8429 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
8432 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
8433 bool GiveMessagesFalse =
false;
8434 bool CheckLocationsExistInRailwayTrue =
true;
8441 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
8444 if(Marker[6] ==
'1')
8909 bool HideFlashingTrain =
true;
8912 Graphics::TBitmap *SmallTrainBitmap;
8953 HideFlashingTrain =
false;
8958 HideFlashingTrain =
false;
8963 HideFlashingTrain =
false;
8968 HideFlashingTrain =
false;
8973 HideFlashingTrain =
false;
8977 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
8981 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
9005 for(
int y = 0; y < 3; y++)
9009 bool FoundFlag =
false;
9020 if(IMPair.first != IMPair.second)
9047 if((LocationName ==
"") && (
MidElement > -1))
9051 if((LocationName ==
"") && (
LagElement > -1))
9055 if(LocationName ==
"")
9057 throw Exception(
"Error - Location name not set in TrainAtLocation");
9068 for(
int x = 0; x < 4; x++)
9080 for(
int x = 0; x < 4; x++)
9097 AnsiString(LinkNumber) +
"," +
HeadCode);
9149 int DistanceToRedSignal = 0, DistanceToExit = -1;
9150 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9154 float MinsEarly = 0;
9155 TDateTime DepartureTime;
9156 TDateTime ArrivalTime;
9184 if(TempTTE < LastTimeToExit)
9219 if(TempTTE < LastTimeToExit)
9242 if(TempTTE < LastTimeToExit)
9272 if(TempTTE < LastTimeToExit)
9295 if(TempTTE < LastTimeToExit)
9338 float CurrentStopTime;
9339 float LaterStopTime;
9340 float RecoverableTime;
9348 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
9355 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
9356 bool DistanceToExitSet = (DistanceToExit > -1);
9357 int GenericDistance = DistanceToRedSignal;
9358 if(DistanceToExitSet)
9360 GenericDistance = DistanceToExit;
9376 float TimeToSubtract, TotalStopTime;
9379 TimeToSubtract = RecoverableTime;
9422 if(CurrentStopTime > 0)
9424 TotalStopTime = CurrentStopTime + LaterStopTime;
9433 else if((MinsEarly > 0) && !
Stopped())
9435 TotalStopTime = LaterStopTime + MinsEarly;
9439 if(LaterStopTime == 0)
9441 TotalStopTime = CurrentStopTime;
9447 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
9450 if(AvTrackSpeed < 30)
9454 int Speed = AvTrackSpeed;
9464 if(DistanceToRedSignalSet)
9466 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9476 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9505 if((NextEntryPos == 0) || (NextEntryPos == 2))
9632 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9674 int IncrementalMinutes = 0;
9675 int IncrementalDigits = 0;
9683 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
9719 if(AVEntry0.
Command ==
"Snt-sh")
9724 int IncrementalMinutes = 0;
9725 int IncrementalDigits = 0;
9733 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
9777 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9857 AnsiString Loc =
"";
9858 bool ElementFound =
false;
9863 ElementFound =
true;
9868 ElementFound =
true;
9873 ElementFound =
true;
9902 else if(AVEntryPtr->
Command ==
"Fer")
9904 bool CorrectExit =
false;
10016 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10034 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10049 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10060 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
10061 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
10062 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
10064 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
10065 "," + AnsiString(Mass) +
"," + ModeStr);
10067 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
10069 int RearExitPos = -1;
10071 for(
int x = 0; x < 4; x++)
10078 if(RearExitPos == -1)
10080 throw Exception(
"Error, RearExit == -1 in AddTrain");
10082 bool ReportFlag =
true;
10087 ReportFlag =
false;
10099 if(ModeStr ==
"Timetable")
10105 if(MaxRunningSpeed < 10)
10107 MaxRunningSpeed = 10;
10109 if(SignallerSpeed < 10)
10111 SignallerSpeed = 10;
10113 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
10114 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10121 if(SignallerControl)
10151 if(!SignallerControl)
10166 if(!SignallerControl)
10177 AnsiString Loc =
"";
10194 if(!SignallerControl)
10213 int RouteNumber = -1;
10214 bool SignalsSet =
false;
10221 int RouteStartPosition;
10225 if(FirstPair.first == RouteNumber)
10227 RouteStartPosition = FirstPair.second;
10229 else if(SecondPair.first == RouteNumber)
10231 RouteStartPosition = SecondPair.second;
10235 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10241 else if(RouteNumber > -1)
10261 int LinkedRouteNumber = -1;
10282 int RouteStartPosition;
10286 if(FirstPair.first == RouteNumber)
10288 RouteStartPosition = FirstPair.second;
10290 else if(SecondPair.first == RouteNumber)
10292 RouteStartPosition = SecondPair.second;
10296 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10302 else if(RouteNumber > -1)
10322 int LinkedRouteNumber = -1;
10343 AnsiString(TrackVectorNumber));
10346 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10355 throw Exception(
"Error, VecPos not set in EntryPos");
10357 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
10362 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
10367 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
10381 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10389 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
10399 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10420 return(RepeatTime);
10429 AnsiString RetStr =
"", PartStr =
"";
10437 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
10445 if(Ptr->SignallerControl)
10447 RetStr =
"Train under signaller control";
10452 if(Ptr->ArrivalTime == Ptr->DepartureTime)
10463 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
10467 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
10471 else if(Ptr->FormatType ==
PassTime)
10475 else if(Ptr->Command ==
"Fns")
10481 else if(Ptr->Command ==
"F-nshs")
10484 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
10491 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10498 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10501 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
10504 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10511 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10513 PartStr =
"Terminate at " + Ptr->LocationName;
10515 else if(Ptr->Command ==
"Frh")
10517 PartStr =
"Terminate at " + Ptr->LocationName;
10519 else if(Ptr->Command ==
"Fer")
10521 AnsiString AllowedExits;
10525 else if(Ptr->Command ==
"Fjo")
10528 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10530 else if(Ptr->Command ==
"jbo")
10533 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10535 else if(Ptr->Command ==
"fsp")
10540 else if(Ptr->Command ==
"rsp")
10545 else if(Ptr->Command ==
"cdt")
10549 else if(Ptr->Command ==
"dsc")
10555 RetStr = RetStr +
'\n' + PartStr;
10563 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
10576 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
10577 AnsiString DepTime =
"", EventTime =
"";
10578 bool CDTFlag =
false;
10580 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
10581 AnsiString TowardsLocation =
"";
10584 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
10586 TowardsLocation = AVI->LocationName;
10588 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
10597 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
10603 if(AVI->Command ==
"cdt")
10605 CDTFlag = !CDTFlag;
10608 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
10611 RetStr +=
"\nNew service splits at " + EventTime;
10615 if(AVI->Command ==
"jbo")
10618 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
10622 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
10625 RetStr +=
"\nNew service finishes and forms another new service at " + EventTime;
10629 if(AVI->Command ==
"Fjo")
10632 RetStr +=
"\nNew service finishes and joins " + AVI->OtherHeadCode +
" at " + EventTime;
10636 if(AVI->Command ==
"Frh")
10638 RetStr +=
"\nNew service finishes and remains at location.";
10642 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
10647 if(TowardsLocation !=
"")
10649 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
10653 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
10658 if(TowardsLocation !=
"")
10660 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
10664 RetStr +=
"\nNew service departs at " + DepTime;
10829 ActiveTrackElementNameMapEntry.second = 0;
10835 std::ifstream TTBLFile(FileName, std::ios_base::binary);
10838 if(TTBLFile.is_open())
10840 char *TrainTimetableString =
new char[10000];
10842 bool EndOfFile =
false;
10845 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10847 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10854 delete[] TrainTimetableString;
10858 AnsiString OneLine(TrainTimetableString);
10859 bool FinalCallFalse =
false;
10860 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10864 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10865 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10870 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
10872 delete[] TrainTimetableString;
10876 OneLine = AnsiString(TrainTimetableString);
10882 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10884 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10894 OneLine = AnsiString(TrainTimetableString);
10896 if(OneLine.Length() > 9999)
10898 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
10900 delete[] TrainTimetableString;
10904 bool FinalCallFalse =
false;
10905 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10909 delete[] TrainTimetableString;
10913 if(EndOfFile && (Count < 2))
10916 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
10918 delete[] TrainTimetableString;
10924 delete[] TrainTimetableString;
10929 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
10940 bool CheckLocationsExistInRailway)
11068 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
11078 if(OneLine[1] !=
'*')
11080 int SCPos = OneLine.Pos(
';');
11091 bool AllCommas =
true;
11093 for(
int x = 1; x < OneLine.Length() + 1; x++)
11095 if(OneLine[x] !=
',')
11100 if(AllCommas || (OneLine ==
""))
11115 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
11116 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
11117 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
11118 TDateTime StartTime(0);
11120 bool Warning =
false;
11147 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
11148 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11149 double MaxBrakeRate = 0;
11150 double PowerAtRail = 0;
11151 int SignallerSpeed = 0;
11152 if(OneLine[1] ==
'*')
11158 int Pos = OneLine.Pos(
',');
11161 int SubStringLength = 20;
11162 if(OneLine.Length() < 20)
11164 SubStringLength = OneLine.Length();
11166 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
11170 TrainInfoStr = OneLine.SubString(1, Pos - 1);
11171 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11182 TempTrainDataEntry.
HeadCode = HeadCode;
11186 if(Description !=
"")
11191 TempTrainDataEntry.
Mass = Mass;
11199 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
11202 while(NewRemainder[NewRemainder.Length()] ==
',')
11204 if(NewRemainder.Length() > 1)
11206 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11215 if(NewRemainder ==
"")
11217 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
11222 int CommaCount = 0;
11223 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11225 if(NewRemainder[x] ==
',')
11230 if(CommaCount == 0)
11232 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11234 int SubStringLength = 20;
11235 if(OneLine.Length() < 20)
11237 SubStringLength = OneLine.Length();
11240 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11241 OneLine.SubString(1, SubStringLength) +
"'....");
11246 AnsiString OneEntry =
"";
11251 bool FinishFlag =
false;
11252 bool NewTrain =
false;
11253 for(
int x = 0; x < CommaCount + 1; x++)
11255 if((CommaCount == 0) || (x < CommaCount))
11260 if(CommaCount == 0)
11262 OneEntry = NewRemainder;
11267 Pos = NewRemainder.Pos(
',');
11268 OneEntry = NewRemainder.SubString(1, Pos - 1);
11269 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
11275 RearStartOrRepeatMins = 0;
11276 FrontStartOrRepeatDigits = 0;
11277 NumberOfRepeats = 0;
11278 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11279 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11281 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11285 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11290 if(Warning && (Second ==
"Frh"))
11292 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
11296 if(Warning && (Second ==
"Fjo"))
11299 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
11305 if(NewTrain && (PowerAtRail < 1) && (Second ==
"jbo"))
11308 "': a train created without power can't 'be joined by' another train (i.e. can't include command 'jbo'), "
11309 "use command 'Fjo' (i.e. 'join' another train) instead immediately after the line containing 'Snt', and use "
11310 "command 'jbo' for the train it is to join.");
11314 if(NewTrain && (PowerAtRail < 1) && ((Second ==
"fsp") || (Second ==
"rsp")))
11317 "': a train created without power can't split.");
11321 if(NewTrain && (PowerAtRail < 1) && (Second ==
"cdt"))
11324 "': a train created without power can't change direction under timetable control.");
11333 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
11337 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
11339 if(NewRemainder[1] !=
'R')
11342 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
11348 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11352 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
11355 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
11361 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
11366 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11371 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
11374 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11390 TDateTime TempTime;
11396 ActionVectorEntry.
Warning = Warning;
11412 ActionVectorEntry.
Command = Second;
11427 else if(FormatType ==
TimeCmd)
11433 ActionVectorEntry.
Command = Second;
11441 ActionVectorEntry.
Command = Second;
11442 ActionVectorEntry.
ExitList = ExitList;
11450 ActionVectorEntry.
Command = Second;
11464 ActionVectorEntry.
Command = Second;
11475 ActionVectorEntry.
Command = Second;
11485 ActionVectorEntry.
Command = Second;
11487 if((Second ==
"fsp") || (Second ==
"rsp"))
11502 ActionVectorEntry.
Command = Second;
11511 ActionVectorEntry.
Command = Second;
11517 ActionVectorEntry.
Command = Second;
11525 ActionVectorEntry.
Command = Second;
11528 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11533 OneEntry = NewRemainder;
11538 RearStartOrRepeatMins = 0;
11539 FrontStartOrRepeatDigits = 0;
11540 NumberOfRepeats = 0;
11541 if((FinishFlag) && (OneEntry[1] !=
'R'))
11544 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
11548 if(OneEntry[1] !=
'R')
11550 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11551 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11553 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11558 if(NewTrain && (PowerAtRail < 1) && ((Second ==
"Fns") || (Second ==
"Frh-sh") || (Second ==
"Fns-sh") || (Second ==
"F-nshs")))
11561 "': a train created without power can't form a new service.");
11568 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
11575 TDateTime TempTime;
11581 ActionVectorEntry.
Warning = Warning;
11588 ActionVectorEntry.
Command = Second;
11596 ActionVectorEntry.
Command = Second;
11605 ActionVectorEntry.
Command = Second;
11614 ActionVectorEntry.
Command = Second;
11624 ActionVectorEntry.
Command = Second;
11625 ActionVectorEntry.
ExitList = ExitList;
11629 ActionVectorEntry.
Command = Second;
11631 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11636 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
11652 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11671 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
11676 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
11691 if(TimeStr.Length() < 5)
11696 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
11701 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
11706 if(TimeStr[3] !=
':')
11711 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
11716 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
11721 while(TimeStr.Length() > 5)
11723 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
11725 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
11726 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
11728 if((WholeHours + FracHour) >= 95.98334)
11733 Time = TDateTime((WholeHours + FracHour) / 24);
11740 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
11741 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
11750 TDateTime TempTime;
11752 if(OneEntry.Length() > 0)
11754 if(OneEntry[1] ==
'W')
11757 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
11761 if(OneEntry ==
"Frh")
11771 if(OneEntry.Length() < 7)
11776 int Pos = OneEntry.Pos(
';');
11784 First = OneEntry.SubString(1, 5);
11790 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
11793 if((Remainder.Length() >= 3) && (Remainder[1] >=
'0') && (Remainder[1] <=
'9') && (Remainder[2] >=
'0') && (Remainder[2] <=
'9') && (Remainder[3] ==
':'))
11796 if(Remainder.Length() < 7)
11801 Pos = Remainder.Pos(
';');
11808 Second = Remainder.SubString(1, 5);
11814 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11827 Pos = Remainder.Pos(
';');
11830 Second = Remainder;
11831 if(Second ==
"cdt")
11856 if((Pos != 4) && (Pos != 7) && (Pos != 8))
11862 Second = Remainder.SubString(1, Pos - 1);
11864 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11866 Pos = Remainder.Pos(
';');
11873 Third = Remainder.SubString(1, Pos - 1);
11874 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11877 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11880 int SpacePos = Third.Pos(
' ');
11886 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
11887 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
11889 if(CheckLocationsExistInRailway)
11899 if(Second ==
"Snt")
11922 if(Second ==
"Sns-sh")
11941 if(Second ==
"F-nshs")
11955 if(Second ==
"Sns-fsh")
11969 if(Second ==
"Fns-sh")
11989 if(Second ==
"pas")
12004 if(Second ==
"Fer")
12011 if(CheckLocationsExistInRailway)
12022 if(Second ==
"dsc")
12024 if(Third.Length() > 60)
12026 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters in '" + Third +
"'");
12030 for(
int x = 1; x < Third.Length() + 1; x++)
12033 if((Third[x] <
' ') && (Third[x] >= 0))
12035 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + Third +
"'");
12051 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
12052 (Second !=
"Frh-sh"))
12064 if(Second ==
"Frh-sh")
12072 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
12076 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
12080 if((Second ==
"Sfs") || (Second ==
"Sns"))
12085 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
12102 bool ErrorFlag =
false;
12104 if((SplitDistributionString.Length() > 6 ) || (SplitDistributionString.Length() < 3))
12108 int pos = SplitDistributionString.Pos(
'-');
12115 AnsiString MassStr = SplitDistributionString.SubString(1, pos - 1);
12116 AnsiString PowerStr = SplitDistributionString.SubString(pos + 1, SplitDistributionString.Length() - pos);
12119 int x = MassStr.ToInt();
12120 int y = PowerStr.ToInt();
12121 if((x > 99) || (x < 1) || (y > 100) || (y < 0))
12126 catch(
const Exception &e)
12133 TimetableMessage(GiveMessages,
"Error in split distribution " + SplitDistributionString +
", should be 'AA-BB' where AA is the percentage mass (min 1, max 99) and BB the percentage " +
12134 "power for the new split-off train");
12155 if((LocStr.Length() >= 3) && (LocStr[1] >=
'0') && (LocStr[1] <=
'9') && (LocStr[2] >=
'0') && (LocStr[2] <=
'9') && (LocStr[3] ==
':'))
12160 for(
int x = 1; x < LocStr.Length() + 1; x++)
12162 if(((LocStr[x] <
' ') && (LocStr[x] >= 0)) || (LocStr[x] ==
',') || (LocStr[x] ==
';'))
12176 if(CheckLocationsExistInRailway)
12181 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
12182 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
12183 "that includes a continuation will not be valid.");
12201 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
12204 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
12209 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
12211 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
12213 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
12219 for(
int x = 3; x >= 0; x--)
12221 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
12222 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
12224 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
12240 AnsiString CurrentID =
"";
12242 if(IDSet.Length() == 0)
12244 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
12248 for(
int x = 1; x <= IDSet.Length(); x++)
12251 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
12253 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
12275 int Pos = IDSet.Pos(
' ');
12286 CurrentID = IDSet.SubString(1, Pos - 1);
12287 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
12299 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
12306 if(!ExitList.empty())
12308 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
12310 if(*ELIT == VecPos)
12312 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
12319 ExitList.push_back(VecPos);
12329 Pos = IDSet.Pos(
' ');
12336 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
12343 AnsiString Remainder =
"";
12344 int SemiColonCount = 0;
12346 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
12348 if(TrainInfoStr[x] ==
';')
12353 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
12355 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
12356 "'. Should be headcode + optional description for a continuing service;" +
12357 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
12361 if(SemiColonCount == 0)
12363 HeadCode = TrainInfoStr;
12372 if(SemiColonCount == 1)
12374 Pos = TrainInfoStr.Pos(
';');
12375 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12376 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12382 if(Description ==
"")
12384 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12388 if(Description.Length() > 60)
12390 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12394 for(
int x = 1; x < Description.Length() + 1; x++)
12397 if((Description[x] <
' ') && (Description[x] >= 0))
12399 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12408 Pos = TrainInfoStr.Pos(
';');
12409 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12410 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12416 Pos = Remainder.Pos(
';');
12417 Description = Remainder.SubString(1, Pos - 1);
12418 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12419 if(Description ==
"")
12421 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12425 if(Description.Length() > 60)
12427 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12431 for(
int x = 1; x < Description.Length() + 1; x++)
12434 if((Description[x] <
' ') && (Description[x] >= 0))
12436 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12441 Pos = Remainder.Pos(
';');
12442 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
12444 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12445 if(StartSpeedStr ==
"")
12447 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
12451 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
12453 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
12455 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
12460 StartSpeed = StartSpeedStr.ToInt();
12466 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12470 Pos = Remainder.Pos(
';');
12471 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
12473 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12474 if(MaxRunningSpeedStr ==
"")
12476 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
12480 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
12482 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
12484 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
12489 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
12495 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12499 if(MaxRunningSpeed < 10)
12502 MaxRunningSpeed = 10;
12505 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12509 Pos = Remainder.Pos(
';');
12510 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
12512 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12515 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
12519 for(
int x = 1; x < MassStr.Length() + 1; x++)
12521 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
12523 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
12528 Mass = MassStr.ToInt() * 1000;
12534 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
12540 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
12544 Pos = Remainder.Pos(
';');
12545 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
12547 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12548 if(MaxBrakeForceStr ==
"")
12550 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
12554 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
12556 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
12558 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
12563 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
12566 if((MaxBrakeForce / Mass) > 1)
12568 MaxBrakeForce = Mass;
12571 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
12575 if((MaxBrakeForce / Mass) < 0.01)
12577 MaxBrakeForce = Mass * 0.01;
12580 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
12585 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
12587 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
12589 if(SemiColonCount == 6)
12591 GrossPowerStr = Remainder;
12592 SignallerSpeedStr =
"30";
12596 Pos = Remainder.Pos(
';');
12597 GrossPowerStr = Remainder.SubString(1, Pos - 1);
12598 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12601 if(GrossPowerStr ==
"")
12603 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
12607 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
12609 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
12611 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
12617 double GrossPower = GrossPowerStr.ToInt() * 1000;
12624 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
12628 else if(GrossPower == 0)
12633 else if((GrossPower > 0) && (GrossPower < 10000))
12636 GrossPower = 10000;
12638 PowerAtRail = GrossPower * 0.8;
12642 if(SignallerSpeedStr ==
"")
12644 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
12648 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
12650 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
12652 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
12657 SignallerSpeed = SignallerSpeedStr.ToInt();
12663 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12667 if(SignallerSpeed < 10)
12670 SignallerSpeed = 10;
12673 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12691 if(OneEntry.Length() < 7)
12693 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12697 int SemiColonCount = 0;
12699 for(
int x = 1; x < OneEntry.Length() + 1; x++)
12701 if(OneEntry[x] ==
';')
12706 if(SemiColonCount != 3)
12708 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12712 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
12714 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12718 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
12723 Pos = Remainder.Pos(
';');
12724 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
12726 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12727 if(MinutesStr ==
"")
12729 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
12733 if(MinutesStr.Length() > 3)
12736 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
12740 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
12742 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
12744 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
12749 RearStartOrRepeatMins = MinutesStr.ToInt();
12750 if(RearStartOrRepeatMins == 0)
12752 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
12756 Pos = Remainder.Pos(
';');
12757 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
12759 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12760 if(DigitsStr ==
"")
12762 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
12766 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
12768 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
12770 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
12775 if(DigitsStr.Length() > 2)
12777 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
12781 FrontStartOrRepeatDigits = DigitsStr.ToInt();
12795 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
12799 AnsiString NumberStr = Remainder;
12801 if(NumberStr ==
"")
12803 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
12807 if(NumberStr.Length() > 4)
12810 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
12814 for(
int x = 1; x < NumberStr.Length() + 1; x++)
12816 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
12819 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
12824 NumberOfRepeats = NumberStr.ToInt();
12825 if(NumberOfRepeats == 0)
12827 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
12999 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
13020 TwoLocationFlag =
false;
13026 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
13040 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
13056 "Error in timetable - a signaller controlled service can have no more than one item (a repeat) after the start event, see: " +
13068 "Error in timetable - a signaller controlled service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
13094 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
13107 SecondPassMessage(GiveMessages,
"Error in timetable - only 'Frh' or 'Fjo' finish events are permitted immediately after an 'Sns' or 'Sfs' event for: " +
13114 if((AVEntry0.
Command ==
"Snt-sh") || (AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13120 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event can't immediately follow an 'Snt-sh', 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
13130 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13135 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
13145 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13150 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
13160 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13171 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
13181 SecondPassMessage(GiveMessages,
"Error in timetable - the event immediately before the repeat must be a finish for: " + TDEntry.
HeadCode);
13193 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13200 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
13209 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " + TDEntry.
HeadCode);
13228 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
13230 AnsiString LocationName =
"";
13244 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
13245 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13254 if(AVEntry0.
Command ==
"Snt-sh")
13268 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
13284 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh', 'Snt-fsh' or 'Sns-fsh' followed by an illegal event for: " +
13285 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13297 bool FoundFlag =
false;
13301 if((AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13303 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13315 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
13328 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13353 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13375 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13397 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13422 bool LocFoundFlag, FnsFoundFlag;
13426 LocFoundFlag =
false;
13427 FnsFoundFlag =
false;
13428 for(
int y =
TrainDataVector.at(x).ActionVector.size() - 1; y >= 0; y--)
13433 FnsFoundFlag =
true;
13442 LocFoundFlag =
true;
13453 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' finish must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13459 if(FnsFoundFlag && !LocFoundFlag)
13461 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' finish must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13474 if(AVEntry0.
Command ==
"Sns")
13486 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sns' event for: " + TDEntry.
HeadCode);
13494 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13495 ". The event isn't valid for a stationary train.");
13503 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13510 TDateTime SnsEventTime = AVEntry0.
EventTime;
13513 bool BreakFlag =
false;
13516 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13521 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SnsServiceRef)
13543 if(AVEntry0.
Command ==
"Sfs")
13545 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13553 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event must be followed by a departure and arrival before another split, see " +
TrainDataVector.at(x).ServiceReference);
13565 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13570 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13590 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13597 SecondPassMessage(GiveMessages,
"Error in timetable - an 'fsp' or 'rsp' event must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13612 if(AVEntry0.
Command ==
"Sfs")
13624 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sfs' event for: " + TDEntry.
HeadCode);
13632 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13633 ". The event isn't valid for a stationary train.");
13641 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13648 TDateTime SfsEventTime = AVEntry0.
EventTime;
13650 bool BreakFlag =
false;
13653 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13658 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SfsServiceRef)
13678 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13683 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13704 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13711 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"' must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13716 else if((AVEntry.
Command ==
"Sns") || (AVEntry.
Command ==
"Sfs"))
13719 "Please make sure that the finish event of the service that links to this event is preceded by an "
13720 "event at the same location that has an identified location name, normally an arrival.");
13725 else if(AVEntry.
Command ==
"Snt-sh")
13728 "Please make sure that the service starts with zero speed and is at a named location.");
13733 else if((AVEntry.
Command ==
"Sns-fsh") || (AVEntry.
Command ==
"Sns-sh"))
13736 "Please make sure that the event is followed (not necessarily immediately) by a departure.");
13743 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13756 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13766 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish event for: " + TDEntry.
HeadCode);
13773 if(AVEntry.
Command ==
"F-nshs")
13778 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
13806 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
13807 ". The event isn't valid for a stationary train.");
13817 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
13825 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
13826 ". The event isn't valid for a stationary train.");
13844 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
13845 ". The event isn't valid for a stationary train.");
13863 SecondPassMessage(GiveMessages,
"Error in timetable - a 'dsc' is followed by an illegal event for: " + TDEntry.
HeadCode +
13864 ". The event isn't valid for a stationary train.");
13874 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
13882 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
13883 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
13901 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
13902 ". The event isn't valid for a moving train.");
13924 bool LastEntryIsAnArrival =
false;
13931 LastEntryIsAnArrival =
false;
13932 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13939 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
13941 if(LastEntryIsAnArrival)
13945 LastEntryIsAnArrival =
false;
13951 LastEntryIsAnArrival =
true;
13958 LastEntryIsAnArrival =
true;
13959 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13966 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
13968 if(LastEntryIsAnArrival)
13972 LastEntryIsAnArrival =
false;
13978 LastEntryIsAnArrival =
true;
13988 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13996 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
14004 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
14005 ". The event isn't valid for a stationary train.");
14016 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
14024 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
14025 ". The event isn't valid for a moving train.");
14039 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14046 throw Exception(
"Timetable error, TimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14050 throw Exception(
"Timetable error, TimeLoc event has neither arrival nor departure time set for " + TDEntry.
HeadCode);
14057 throw Exception(
"Timetable error, TimeTimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14061 throw Exception(
"Timetable error, TimeTimeLoc event has either arrival or departure time not set for " + TDEntry.
HeadCode);
14070 throw Exception(
"Timetable error, Cmd or PassTime event has EventTime not set for " + TDEntry.
HeadCode);
14074 throw Exception(
"Timetable error, Cmd or PassTime event has either arrival or departure time set for " + TDEntry.
HeadCode);
14081 throw Exception(
"Timetable error, Repeat event has a time set for " + TDEntry.
HeadCode);
14092 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14107 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
14115 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
14130 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14142 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14154 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
14155 ", may be before timetable start time");
14166 AnsiString LastLocationName =
"";
14170 bool LastEntryIsAnArrival =
false;
14175 LastEntryIsAnArrival =
false;
14176 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14177 if(LastLocationName !=
"")
14179 throw Exception(
"Timetable error, moving Snt event has LocationName set for " + TDEntry.
HeadCode);
14181 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
14194 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14206 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14219 TwoLocationFlag =
true;
14224 LastEntryIsAnArrival =
false;
14228 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14231 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14236 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
14239 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
14245 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14251 LastEntryIsAnArrival =
true;
14252 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14253 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14265 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14277 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14290 TwoLocationFlag =
true;
14295 LastEntryIsAnArrival =
false;
14299 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14302 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14310 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
14317 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14325 AnsiString LocationNameToBeChecked =
"";
14330 unsigned int y = 0;
14344 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
14345 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
14363 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
14372 TwoLocationFlag =
true;
14383 if(TwoLocationFlag)
14393 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14398 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat event doesn't have a location name set for " + TDEntry.
HeadCode);
14400 AnsiString LocName =
"";
14406 throw Exception(
"Error, 'Snt' event at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
14413 throw Exception(
"Error, 'Snt' unlocated event has a location name set for " + TDEntry.
HeadCode);
14436 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14461 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14483 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14505 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14524 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14527 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
14542 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14547 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
14551 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
14555 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
14559 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
14598 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14600 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
14606 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
14619 int IncMinutes = 0;
14629 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14635 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
14641 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
14646 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14652 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
14657 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14670 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14696 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
14704 if(HeadCode.Length() > 4)
14706 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
14717 int ForwardCount = 0;
14718 int ReverseCount = 0;
14720 if(MainHeadCode == SecondHeadCode)
14722 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
14731 if(TDEntry.
HeadCode == MainHeadCode)
14733 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14748 if(ForwardCount == 0)
14751 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
14753 if(ForwardCount > 2)
14756 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
14757 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
14766 if(TDEntry.
HeadCode == SecondHeadCode)
14768 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14783 if(ReverseCount == 0)
14785 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
14790 if(ReverseCount > 2)
14793 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
14794 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
14799 if(ForwardCount != ReverseCount)
14801 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
14802 " than the other way round");
14833 int ForwardCount = 0;
14834 int ReverseCount = 0;
14835 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
14844 if(TDEntry.
HeadCode == MainHeadCode)
14846 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14849 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
14854 ForwardEntryPtr = &AVEntry;
14856 ForwardTDVectorNumber = x;
14859 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
14860 (AVEntry.
Command ==
"Frh-sh")))
14865 ForwardEntryPtr = &AVEntry;
14867 ForwardTDVectorNumber = x;
14873 if(ForwardCount == 0)
14876 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
14878 if(ForwardCount > 1)
14880 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
14890 if(TDEntry.
HeadCode == OtherHeadCode)
14892 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14895 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
14901 ReverseEntryPtr = &AVEntry;
14902 ReverseTDVectorNumber = x;
14905 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
14911 ReverseEntryPtr = &AVEntry;
14912 ReverseTDVectorNumber = x;
14919 if(ReverseCount == 0)
14921 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
14926 if(ReverseCount > 1)
14928 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
14935 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
14936 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
14937 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
14938 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
14942 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
14949 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
14954 if(SetDataAndCheckLocations)
14956 if(ForwardEntryPtr->LocationName ==
"")
14958 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
14959 ". One or other service does not have a location set");
14966 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
14967 ". One or other service does not have a location set");
14972 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
14974 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
14975 " is at a different location to the referencing train " + MainHeadCode);
14984 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
14986 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
14987 " has a different event time to the referencing train " + MainHeadCode);
14995 if(ForwardShuttleStart && ReverseShuttleFinish)
15000 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
15001 " first repeat restart time not consistent with finish service " + OtherHeadCode);
15007 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
15010 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15012 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
15013 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15019 if(ReverseEntryPtr->
Command ==
"Fjo")
15022 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15024 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
15025 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15031 if(ReverseEntryPtr->
Command ==
"Fns")
15034 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15036 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
15037 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15043 if(ForwardEntryPtr->Command ==
"Sfs")
15045 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
15048 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
15055 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
15057 if(ReverseEntryPtr->
Command !=
"Sfs")
15059 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
15067 if(SetDataAndCheckLocations)
15071 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
15078 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
15084 bool StationLocation =
false;
15087 if(TEIt->LocationName == ForwardEntryPtr->LocationName)
15091 StationLocation =
true;
15095 if(StationLocation)
15099 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15109 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15115 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15127 if(ForwardEntryPtr->Command ==
"Sns")
15129 if(ReverseEntryPtr->
Command !=
"Fns")
15131 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
15132 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
15138 if(ForwardEntryPtr->Command ==
"Fns")
15140 if(ReverseEntryPtr->
Command !=
"Sns")
15142 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
15143 " and forms a new service with headcode " + OtherHeadCode);
15150 if(SetDataAndCheckLocations)
15152 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15164 if(ForwardEntryPtr->Command ==
"jbo")
15166 if(ReverseEntryPtr->
Command !=
"Fjo")
15168 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
15169 " and is joined by a train with headcode " + OtherHeadCode);
15175 if(ForwardEntryPtr->Command ==
"Fjo")
15177 if(ReverseEntryPtr->
Command !=
"jbo")
15179 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
15180 " and joins a train with headcode " + OtherHeadCode);
15187 if(SetDataAndCheckLocations)
15189 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15205 if(ForwardShuttleStart)
15208 if(!ReverseShuttleFinish)
15211 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
15212 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
15218 if(ReverseShuttleStart)
15221 if(!ForwardShuttleFinish)
15224 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
15225 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
15232 if(SetDataAndCheckLocations)
15234 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15247 bool MainRepeat =
false, OtherRepeat =
false;
15257 OtherRepeat =
true;
15260 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
15262 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
15263 " and the associated train with headcode " + OtherHeadCode);
15268 if(MainRepeat && OtherRepeat)
15274 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
15275 " and the associated train with headcode " + OtherHeadCode);
15297 while(Input[1] ==
' ')
15299 if(Input.Length() > 1)
15301 Input = Input.SubString(2, Input.Length() - 1);
15315 while(Input[Input.Length()] ==
' ')
15317 if(Input.Length() > 1)
15319 Input = Input.SubString(1, Input.Length() - 1);
15329 AnsiString Output =
"";
15330 bool DelimiterFound =
false;
15332 for(
int x = 1; x < Input.Length() + 1; x++)
15336 if(Input[x] ==
' ')
15341 if((Input[x] !=
',') && (Input[x] !=
';'))
15343 DelimiterFound =
false;
15344 Output = Output + Input[x];
15348 DelimiterFound =
true;
15349 Output = Output + Input[x];
15361 DelimiterFound =
false;
15362 for(
int x = Input.Length(); x > 0; x--)
15366 if(Input[x] ==
' ')
15371 if((Input[x] !=
',') && (Input[x] !=
';'))
15373 DelimiterFound =
false;
15374 Output = AnsiString(Input[x]) + Output;
15378 DelimiterFound =
true;
15379 Output = AnsiString(Input[x]) + Output;
15404 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
15406 throw Exception(
"Error, first event not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
15418 LocationName = LocRear;
15422 LocationName = LocFront;
15424 if(LocationName ==
"")
15445 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
15486 int RearPosition = 0, FrontPosition = 0;
15489 if(RearPosition < 0)
15496 if(FrontPosition < 0)
15508 for(
int x = 0; x < 4; x++)
15510 if(RearTrackElement.
Conn[x] == FrontPosition)
15525 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
15532 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
15538 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
15569 AnsiString(RearExitPos));
15580 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
15582 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
15585 AnsiString RearName, FrontName;
15601 FrontName = FrontTrackElement.
ElementID;
15604 int LockedVectorNumber;
15724 if(((RearTrackElement.
Attribute == 1) && (RearExitPos == 1)) || ((RearTrackElement.
Attribute == 0) && (RearExitPos == 3)))
15729 StopTTClockMessage(157, HeadCode +
" can't be created, points set wrongly at " + RearName);
15737 if(((FrontTrackElement.
Attribute == 1) && (FrontEntryPos == 1)) || ((FrontTrackElement.
Attribute == 0) && (FrontEntryPos == 3)))
15742 StopTTClockMessage(158, HeadCode +
" can't be created, points set wrongly at " + RearName);
15776 "," + AnsiString(IncDigits));
15779 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
15784 return(BaseHeadCode);
15786 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
15787 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
15789 while(NextRepeatDigits >= 100)
15791 NextRepeatDigits -= 100;
15793 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
15795 if(NextRepeatDigitsStr.Length() < 2)
15797 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
15799 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
15802 return(NextRepeatHeadCode);
15810 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
15811 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
15813 return(NextRepeatTime);
15822 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
15823 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
15824 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
15825 int RepeatSecs = RepeatMinutes * 60;
15827 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
15861 NonRepeatingHeadCode);
15862 int ForwardCount = 0;
15863 int ReverseCount = 0;
15864 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15874 if(TDEntry.
HeadCode == MainHeadCode)
15876 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15882 ForwardEntryPtr = &AVEntry;
15884 ForwardTDVectorNumber = x;
15889 if(ForwardCount == 0)
15892 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
15894 if(ForwardCount > 1)
15896 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
15906 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
15908 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15915 ReverseEntryPtr = &AVEntry;
15916 ReverseTDVectorNumber = x;
15922 if(ReverseCount == 0)
15924 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
15929 if(ReverseCount > 1)
15931 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
15932 NonRepeatingHeadCode);
15937 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
15939 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
15944 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
15946 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
15951 if(SetDataAndCheckLocations)
15953 if(ForwardEntryPtr->LocationName ==
"")
15955 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
15956 ". One or other service does not have a location set");
15963 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
15964 ". One or other service does not have a location set");
15969 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
15971 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
15972 " is at a different location to the referencing train " + MainHeadCode);
15978 if(ForwardEntryPtr->Command ==
"F-nshs")
15981 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
15983 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
15984 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
15990 if(ForwardEntryPtr->Command ==
"Fns-sh")
15994 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
15996 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
15997 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
16003 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
16006 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16008 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
16009 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
16027 if(ForwardEntryPtr->Command ==
"Sns-sh")
16029 if(ReverseEntryPtr->
Command !=
"F-nshs")
16031 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
16032 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
16038 if(ForwardEntryPtr->Command ==
"F-nshs")
16040 if(ReverseEntryPtr->
Command !=
"Sns-sh")
16042 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
16043 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
16050 if(SetDataAndCheckLocations)
16052 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16064 if(ForwardEntryPtr->Command ==
"Sns-fsh")
16066 if(ReverseEntryPtr->
Command !=
"Fns-sh")
16069 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
16070 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
16076 if(ForwardEntryPtr->Command ==
"Fns-sh")
16078 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
16081 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
16082 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
16089 if(SetDataAndCheckLocations)
16091 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
16115 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
16116 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16117 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16118 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
16120 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
16144 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
16147 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
16148 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16150 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16152 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16157 while(LastActionCommand ==
"Fns")
16159 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
16160 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16161 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16164 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
16165 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16172 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
16175 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
16176 ". The linking of two or more shuttles is not permitted.");
16214 ShowMessage(Message);
16223 int Mins = Input, Hrs = 0;
16229 AnsiString AnsiMins = AnsiString(Mins);
16230 if(AnsiMins.Length() == 1)
16232 AnsiMins =
"0" + AnsiMins;
16234 AnsiString AnsiHrs = AnsiString(Hrs);
16235 if(AnsiHrs.Length() == 1)
16237 AnsiHrs =
"0" + AnsiHrs;
16240 return(AnsiHrs +
':' + AnsiMins);
16280 AnsiString(ActionEventType) +
"," + LocationID);
16281 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
16286 Prefix =
" ERROR: ";
16289 Prefix =
" HELD: ";
16290 ErrorLog =
" can't enter railway, train obstructing entry position ";
16291 WarningStr =
" can't enter railway, train obstructing entry position ";
16296 Prefix =
" HELD: ";
16297 ErrorLog =
" can't enter railway, route set against it at entry position ";
16298 WarningStr =
" can't enter railway, route set against it at entry position ";
16303 Prefix =
" HELD: ";
16304 ErrorLog =
" can't be created, train obstructing ";
16305 WarningStr =
" can't be created, train obstructing ";
16310 Prefix =
" HELD: ";
16311 ErrorLog =
" can't be created on a locked route at ";
16312 WarningStr =
" can't be created on a locked route at ";
16317 Prefix =
" HELD: ";
16318 ErrorLog =
" can't enter on a locked route at ";
16319 WarningStr =
" can't enter on a locked route at ";
16324 Prefix =
" HELD: ";
16325 ErrorLog =
" can't be created, points set wrongly at ";
16326 WarningStr =
" can't be created, points set wrongly at ";
16331 ErrorLog =
" left railway unexpectedly at ";
16336 ErrorLog =
" left railway at an incorrect exit at ";
16341 ErrorLog =
" failed to split - location too short at ";
16342 WarningStr =
" failed to split, location too short at ";
16347 Prefix =
" HELD: ";
16348 ErrorLog =
" unable to split - other train obstructing at ";
16349 WarningStr =
" unable to split - other train obstructing at ";
16354 ErrorLog =
" stopped at buffers unexpectedly at position ";
16358 ErrorLog =
" failed to stop at ";
16363 ErrorLog =
" failed to split at ";
16368 ErrorLog =
" failed to be joined by other train at ";
16373 ErrorLog =
" failed to change its description at ";
16378 ErrorLog =
" failed to join other train at ";
16383 ErrorLog =
" failed to terminate at ";
16388 ErrorLog =
" failed to form new service at ";
16393 ErrorLog =
" failed to exit railway ";
16398 ErrorLog =
" failed to change direction at ";
16403 ErrorLog =
" failed to pass ";
16408 ErrorLog =
" facing buffers and unable to start at ";
16412 ErrorLog =
" DERAILED at position ";
16413 Prefix =
" DERAILMENT: ";
16418 ErrorLog =
" CRASHED INTO BUFFERS at ";
16419 Prefix =
" CRASH: ";
16424 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
16425 Prefix =
" CRASH: ";
16430 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
16431 Prefix =
" CRASH: ";
16435 else if(ActionEventType ==
FailSPAD)
16437 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
16438 Prefix =
" SPAD: ";
16443 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
16444 Prefix =
" SPAD RISK: ";
16449 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
16453 Prefix =
" WARNING: ";
16454 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
16455 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
16460 Prefix =
" WARNING: ";
16461 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
16462 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
16500 std::ofstream OutFile(
"TrainData.csv");
16504 ShowMessage(
"Output file TrainData.csv failed to open");
16511 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
16516 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
16517 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
16518 "RepeatNumber" <<
'\n' <<
'\n';
16519 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16522 AnsiString TimetableEntryTypeStr;
16528 TimetableEntryTypeStr =
"NoFormat";
16534 TimetableEntryTypeStr =
"TimeLoc";
16540 TimetableEntryTypeStr =
"TimeTimeLoc";
16546 TimetableEntryTypeStr =
"TimeCmd";
16552 TimetableEntryTypeStr =
"StartNew";
16558 TimetableEntryTypeStr =
"TimeCmdHeadCode";
16564 TimetableEntryTypeStr =
"FinRemHere";
16570 TimetableEntryTypeStr =
"FNSShuttle";
16576 TimetableEntryTypeStr =
"SNTShuttle";
16582 TimetableEntryTypeStr =
"SNSShuttle";
16588 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
16594 TimetableEntryTypeStr =
"FSHNewService";
16600 TimetableEntryTypeStr =
"Repeat";
16606 TimetableEntryTypeStr =
"Default";
16617 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
16618 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
16621 AnsiString RunningEntryStr;
16627 RunningEntryStr =
"NotStarted";
16633 RunningEntryStr =
"Running";
16639 RunningEntryStr =
"Exited";
16643 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
16660 ShowMessage(Message);
16661 BaseTime = TDateTime::CurrentDateTime();
16675 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
16688 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16690 for(
int x = 0; x < NumberOfTrains; x++)
16692 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16712 int NumberOfTrains;
16719 for(
int x = 0; x < NumberOfTrains; x++)
16756 for(
int x = 0; x < LockedRouteVectorSize; x++)
16763 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
16774 int LockedRouteVectorSize;
16781 for(
int x = 0; x < LockedRouteVectorSize; x++)
16839 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
16847 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
16858 int ContinuationAutoSigVectorSize;
16865 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
16935 if(AVFirstEntry.
Command ==
"Snt")
16959 CTEMMP.second = CTEEntry;
16966 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
16974 CTEMMP.second = CTEEntry;
16995 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17012 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
17014 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
17025 AnsiString RetStr =
"", PartStr =
"";
17140 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17144 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17146 AnsiString ShortTTName =
"";
17148 for(
int x = TTFileName.Length(); x > 0; x--)
17150 if(TTFileName[x] ==
'\\')
17152 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
17157 ShowMessage(
"Creates two timetables named " + ShortTTName +
17158 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
17160 Screen->Cursor = TCursor(-11);
17162 AnsiString FormatNoDPStr =
"#######0";
17163 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
17166 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
17173 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
17175 if(TrainDataEntry.
Mass > 0)
17177 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
17181 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
17185 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
17189 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
17191 FirstHeadCode = TrainDataEntry.
HeadCode;
17192 int IncDigits = 0, IncMinutes = 0;
17194 if(!ActionVector.empty())
17196 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
17198 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
17199 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17217 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17222 AnsiString PartStr =
"", TimeStr =
"";
17239 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17243 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
17253 PartStr =
"Enters at " + LocName;
17266 PartStr =
"Created at " + LocName;
17280 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17285 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17291 else if(ActionVectorEntry.
Command ==
"Sfs")
17293 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
17297 else if(ActionVectorEntry.
Command ==
"Sns")
17299 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17307 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17313 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17321 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17324 AnsiString FirstHeadCode = TDE->
HeadCode;
17328 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
17340 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17342 OneTTEntry.
Action = PartStr;
17343 OneTTEntry.
Time = TimeStr;
17345 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17350 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
17356 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17361 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17369 else if(ActionVectorEntry.
Command ==
"jbo")
17371 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
17375 else if(ActionVectorEntry.
Command ==
"fsp")
17379 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17383 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17388 else if(ActionVectorEntry.
Command ==
"rsp")
17392 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17396 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17401 else if(ActionVectorEntry.
Command ==
"cdt")
17403 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
17406 else if(ActionVectorEntry.
Command ==
"dsc")
17408 PartStr =
"Changes description at " + ActionVectorEntry.
LocationName;
17414 if(ActionVectorEntry.
Command ==
"Fns")
17416 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17420 else if(ActionVectorEntry.
Command ==
"F-nshs")
17422 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17428 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
17435 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17441 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17448 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
17453 else if(ActionVectorEntry.
Command ==
"Frh")
17455 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
17460 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
17464 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
17474 else if(ActionVectorEntry.
Command ==
"Fer")
17476 AnsiString AllowedExits;
17480 else if(ActionVectorEntry.
Command ==
"Fjo")
17482 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
17491 OneTTEntry.
Action = PartStr;
17492 OneTTEntry.
Time = TimeStr;
17499 AllTTTrains->push_back(OneTTLine);
17503 std::ofstream TTFile(TTFileName.c_str());
17507 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
17508 delete AllTTTrains;
17543 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
17544 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17546 TTFile << AllTTTrains->at(x).Header.c_str();
17549 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17551 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17553 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
17557 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
17560 TTFile <<
'\n' <<
'\n';
17562 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
17564 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
17565 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17567 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17569 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
17573 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
17578 TTFile <<
'\n' <<
'\n';
17583 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17585 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
17587 std::ofstream TTFile2(TTFileName2.c_str());
17591 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
17592 delete AllTTTrains;
17596 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
17597 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
17598 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
17600 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
17605 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
17606 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17608 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17610 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
17612 bool GiveMessagesFalse =
false;
17613 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
17614 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
17615 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
17620 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
17621 TimeString = TimeString.SubString(9, 5);
17622 ActionString +=
" " + OtherHeadCode;
17624 if(TimeString.SubString(1, 7) ==
"End at ")
17627 TimeString = TimeString.SubString(8, 5);
17629 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
17630 AnsiMultiMapEntry.first = TimeString;
17631 AnsiMultiMapEntry.second = OneLine;
17632 TAMM->insert(AnsiMultiMapEntry);
17637 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
17639 TTFile2 << (AMMIT->second).c_str();
17641 delete AllTTTrains;
17650 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
17654 bool AnalysisError =
false;
17655 AnsiString SequenceLog =
"SequenceLog\n";
17698 TTrainDataVector::iterator TDVIt, TDVCopyIt;
17700 int IteratorNumber = 0;
17701 AnsiString AnsiSuffix =
"";
17708 if(TDVCopyIt->HeadCode == TDVIt->HeadCode)
17711 AnsiSuffix = AnsiString(Suffix);
17712 TDVCopyIt->ServiceReference = TDVIt->HeadCode +
"/" + AnsiSuffix;
17713 TDVCopyIt->HeadCode = TDVIt->HeadCode +
"/" + AnsiSuffix;
17719 int Increment = 0, SlashPos;
17721 AnsiString LinkedHeadCode;
17725 for(AVEIt = TDVCopyIt->ActionVector.begin(); AVEIt != TDVCopyIt->ActionVector.end(); AVEIt++)
17727 if(AVEIt->LinkedTrainEntryPtr != NULL)
17736 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
17738 if(LinkedHeadCode[x] ==
'/')
17740 SlashPos = LinkedHeadCode.Length() - x + 1;
17743 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
17744 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
17745 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
17751 AVEIt->OtherHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
17755 AVEIt->OtherHeadCode =
"";
17757 if(AVEIt->NonRepeatingShuttleLinkEntryPtr != NULL)
17759 Increment = AVEIt->NonRepeatingShuttleLinkEntryPtr - &
TrainDataVector.at(0);
17763 LinkedHeadCode = (*AVEIt->NonRepeatingShuttleLinkEntryPtr).
ServiceReference;
17766 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
17768 if(LinkedHeadCode[x] ==
'/')
17770 SlashPos = LinkedHeadCode.Length() - x + 1;
17773 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
17774 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
17775 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
17781 AVEIt->NonRepeatingShuttleLinkHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
17785 AVEIt->NonRepeatingShuttleLinkHeadCode =
"";
17790 SequenceLog +=
"1\n";
17793 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
17799 ServiceCallingLocsList.clear();
17800 if(ActionVector.empty())
17804 if(ActionVector.at(0).SignallerControl)
17808 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17826 int HLoc = TE.
HLoc;
17827 int VLoc = TE.
VLoc;
17828 AnsiString HString;
17829 AnsiString VString;
17832 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
17836 HString = AnsiString(HLoc);
17840 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
17844 VString = AnsiString(VLoc);
17846 ServiceCallingLocsList.push_back(HString +
'-' + VString);
17869 else if(AVE.
Command ==
"cdt")
17882 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
17891 ServiceCallingLocsList.push_back(LName);
17895 int HLoc = TE.
HLoc;
17896 int VLoc = TE.
VLoc;
17897 AnsiString HString;
17898 AnsiString VString;
17901 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
17905 HString = AnsiString(HLoc);
17909 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
17913 VString = AnsiString(VLoc);
17915 ServiceCallingLocsList.push_back(HString +
'-' + VString);
17919 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
17923 SequenceLog +=
"2\n";
17952 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
17958 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
17959 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
17960 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
17962 SequenceLog +=
"3\n";
17969 TDateTime LastTDTime;
17970 int IncMinutes = 0;
17972 if(ActionVector.empty())
17976 if(ActionVector.at(0).SignallerControl)
17980 if(AVLast->FormatType ==
Repeat)
17982 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17990 if(AVLast->ArrivalTime != TDateTime(-1))
17992 LastTDTime = AVLast->ArrivalTime;
17994 else if(AVLast->EventTime != TDateTime(-1))
17996 LastTDTime = AVLast->EventTime;
18015 SequenceLog +=
"4\n";
18052 int IncMinutes = 0;
18054 if(ActionVector.empty())
18058 if(ActionVector.at(0).SignallerControl)
18062 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
18064 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18066 for(
int y = 0; y < NumTrains; y++)
18080 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18095 LocServiceTimesVector.push_back(TLSTEntry);
18098 AnsiString IncTime =
"", FoundStopTime =
"";
18099 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18101 if(ActionVector.at(a).FormatType ==
TimeLoc)
18112 if(FoundStopTime ==
"")
18114 throw Exception(
"Failure to determine FoundStopTime for located Snt");
18116 int WhileCount = 0;
18125 if(IncTime >= FoundStopTime)
18129 LocServiceTimesVector.push_back(TLSTEntry);
18130 if(WhileCount > 2000)
18132 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
18145 int HLoc = TE.
HLoc;
18146 int VLoc = TE.
VLoc;
18147 AnsiString HString;
18148 AnsiString VString;
18151 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18155 HString = AnsiString(HLoc);
18159 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18163 VString = AnsiString(VLoc);
18165 TLSTEntry.
Location = HString +
'-' + VString;
18169 LocServiceTimesVector.push_back(TLSTEntry);
18177 LocServiceTimesVector.push_back(TLSTEntry);
18179 AnsiString IncTime =
"", FoundStopTime =
"";
18180 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18182 if(ActionVector.at(a).FormatType ==
TimeLoc)
18193 if(FoundStopTime ==
"")
18195 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18197 int WhileCount = 0;
18206 if(IncTime >= FoundStopTime)
18210 LocServiceTimesVector.push_back(TLSTEntry);
18211 if(WhileCount > 2000)
18213 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18223 bool SkipAddingMinutes =
false;
18226 LocServiceTimesVector.push_back(TLSTEntry);
18228 AnsiString IncTime =
"", FoundStopTime =
"";
18229 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18231 if(ActionVector.at(a).FormatType ==
TimeLoc)
18239 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr != NULL) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr != NULL)))
18243 LocServiceTimesVector.pop_back();
18244 SkipAddingMinutes =
true;
18249 if(FoundStopTime ==
"")
18251 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18253 if(!SkipAddingMinutes)
18255 int WhileCount = 0;
18264 if(IncTime >= FoundStopTime)
18268 LocServiceTimesVector.push_back(TLSTEntry);
18269 if(WhileCount > 2000)
18271 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18280 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
18282 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
18284 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
18285 LocServiceTimesVector.pop_back();
18286 LocServiceTimesVector.push_back(TLSTEntry);
18291 LocServiceTimesVector.push_back(TLSTEntry);
18297 LocServiceTimesVector.push_back(TLSTEntry);
18316 LocServiceTimesVector.push_back(TLSTEntry);
18320 AnsiString TempDepTime = TLSTEntry.
DepTime;
18322 LocServiceTimesVector.push_back(TLSTEntry);
18324 while(TLSTEntry.
AtLocTime < TempDepTime)
18329 TLSTEntry.
DepTime = TempDepTime;
18330 LocServiceTimesVector.push_back(TLSTEntry);
18334 LocServiceTimesVector.push_back(TLSTEntry);
18345 LocServiceTimesVector.push_back(TLSTEntry);
18348 LocServiceTimesVector.push_back(TLSTEntry);
18365 AnsiString HString;
18366 AnsiString VString;
18369 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18373 HString = AnsiString(HLoc);
18377 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18381 VString = AnsiString(VLoc);
18383 TLSTEntry.
Location = HString +
'-' + VString;
18385 LocServiceTimesVector.push_back(TLSTEntry);
18390 AnsiString FrhTime;
18391 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
18395 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
18403 LocServiceTimesVector.push_back(TLSTEntry);
18409 LocServiceTimesVector.push_back(TLSTEntry);
18414 else if(AVE.
Command ==
"Frh-sh")
18416 if(y == NumTrains - 1)
18422 LocServiceTimesVector.push_back(TLSTEntry);
18428 LocServiceTimesVector.push_back(TLSTEntry);
18441 SequenceLog +=
"5\n";
18474 TLocServiceTimesVector::iterator Ptr1, Ptr2;
18477 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18478 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
18480 std::ofstream TTFile3(TTFileName3.c_str());
18484 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
18488 if(LocServiceTimesVector.empty())
18490 ShowMessage(
"No timetabled services found");
18492 DeleteFile(TTFileName3);
18496 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
18497 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
18498 SequenceLog +=
"6\n";
18727 Ptr1 = LocServiceTimesVector.begin();
18729 while(Ptr2 != LocServiceTimesVector.end())
18731 while(Ptr2->Location == Ptr1->Location)
18734 if(Ptr2 == LocServiceTimesVector.end())
18741 if(Ptr2 != LocServiceTimesVector.end())
18749 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
18750 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
18751 MinuteString =
" minutes";
18752 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
18755 MinuteString =
" minute";
18757 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
18758 TTFile3 <<
",Platforms,Trains\n\n";
18760 Ptr1 = LocServiceTimesVector.begin();
18762 while(Ptr2 != LocServiceTimesVector.end())
18764 PreviousService =
"";
18765 NumTrainsAtLoc = 0;
18766 ServiceAndRepeatNumTotal =
"";
18768 NumPlatsAtThisLocCalculated =
false;
18770 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
18772 PreviousService =
"";
18773 NumTrainsAtLoc = 0;
18774 ServiceAndRepeatNumTotal =
"";
18776 NumPlatsAtThisLocCalculated =
false;
18780 if(Ptr2 == LocServiceTimesVector.end())
18785 if(Ptr2 == LocServiceTimesVector.end())
18789 while(Ptr2->Location == Ptr1->Location)
18791 PreviousService =
"";
18792 NumTrainsAtLoc = 0;
18793 ServiceAndRepeatNumTotal =
"";
18794 BasicTime = Ptr1->ArrTime;
18795 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
18799 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
18801 BasicTime = Ptr2->ArrTime;
18804 if(Ptr2 == LocServiceTimesVector.end())
18808 if(Ptr2->Location != Ptr1->Location)
18813 if(Ptr2 == LocServiceTimesVector.end())
18817 if(Ptr2->Location != Ptr1->Location)
18823 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
18827 if(!NumPlatsAtThisLocCalculated)
18830 NumPlatsAtThisLocCalculated =
true;
18832 if(Ptr1->ServiceAndRepeatNum != PreviousService)
18834 if(ServiceAndRepeatNumTotal ==
"")
18836 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
18837 NumTrainsAtLoc = 1;
18841 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
18844 PreviousService = Ptr2->ServiceAndRepeatNum;
18845 if(ServiceAndRepeatNumTotal ==
"")
18847 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
18848 NumTrainsAtLoc = 1;
18852 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
18856 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
18858 int MaxNumberOfSameDirections = 0;
18859 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
18864 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
18868 AnsiString Asterisk =
"";
18869 if(MaxNumberOfSameDirections >= NumPlats)
18874 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
18875 ArrivalsPrinted =
true;
18876 ServiceAndRepeatNumTotal =
"";
18878 if(Ptr2 == LocServiceTimesVector.end())
18882 if(Ptr2->Location != Ptr1->Location)
18887 if(Ptr2 == LocServiceTimesVector.end())
18893 if(!ArrivalsPrinted)
18895 TTFile3 <<
"Nothing to report for arrivals";
18900 SequenceLog +=
"7\n";
18905 Ptr1 = LocServiceTimesVector.begin();
18907 while(Ptr2 != LocServiceTimesVector.end())
18909 while(Ptr2->Location == Ptr1->Location)
18912 if(Ptr2 == LocServiceTimesVector.end())
18919 if(Ptr2 != LocServiceTimesVector.end())
18926 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
18927 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
18928 MinuteString =
" minutes";
18929 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
18932 MinuteString =
" minute";
18934 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
18935 TTFile3 <<
",Platforms,Trains\n\n";
18937 Ptr1 = LocServiceTimesVector.begin();
18939 while(Ptr2 != LocServiceTimesVector.end())
18941 PreviousService =
"";
18942 NumTrainsAtLoc = 0;
18943 ServiceAndRepeatNumTotal =
"";
18945 NumPlatsAtThisLocCalculated =
false;
18947 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
18949 PreviousService =
"";
18950 NumTrainsAtLoc = 0;
18951 ServiceAndRepeatNumTotal =
"";
18953 NumPlatsAtThisLocCalculated =
false;
18957 if(Ptr2 == LocServiceTimesVector.end())
18962 if(Ptr2 == LocServiceTimesVector.end())
18966 while(Ptr2->Location == Ptr1->Location)
18968 PreviousService =
"";
18969 NumTrainsAtLoc = 0;
18970 ServiceAndRepeatNumTotal =
"";
18971 BasicTime = Ptr1->DepTime;
18972 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
18976 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
18978 BasicTime = Ptr2->DepTime;
18981 if(Ptr2 == LocServiceTimesVector.end())
18985 if(Ptr2->Location != Ptr1->Location)
18990 if(Ptr2 == LocServiceTimesVector.end())
18994 if(Ptr2->Location != Ptr1->Location)
19000 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
19004 if(!NumPlatsAtThisLocCalculated)
19007 NumPlatsAtThisLocCalculated =
true;
19009 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19011 if(ServiceAndRepeatNumTotal ==
"")
19013 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19014 NumTrainsAtLoc = 1;
19018 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19021 PreviousService = Ptr2->ServiceAndRepeatNum;
19022 if(ServiceAndRepeatNumTotal ==
"")
19024 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19025 NumTrainsAtLoc = 1;
19029 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19033 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
19035 int MaxNumberOfSameDirections = 0;
19036 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
19041 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19045 AnsiString Asterisk =
"";
19046 if(MaxNumberOfSameDirections >= NumPlats)
19051 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19052 DeparturesPrinted =
true;
19053 ServiceAndRepeatNumTotal =
"";
19055 if(Ptr2 == LocServiceTimesVector.end())
19059 if(Ptr2->Location != Ptr1->Location)
19064 if(Ptr2 == LocServiceTimesVector.end())
19070 if(!DeparturesPrinted)
19072 TTFile3 <<
"Nothing to report for departures";
19077 SequenceLog +=
"8\n";
19084 Ptr1 = LocServiceTimesVector.begin();
19086 while(Ptr2 != LocServiceTimesVector.end())
19088 while(Ptr2->Location == Ptr1->Location)
19091 if(Ptr2 == LocServiceTimesVector.end())
19098 if(Ptr2 != LocServiceTimesVector.end())
19105 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
19106 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
19107 TTFile3 <<
",Platforms,Trains,\n\n";
19108 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19109 Ptr1 = LocServiceTimesVector.begin();
19111 while(Ptr2 != LocServiceTimesVector.end())
19113 PreviousService =
"";
19114 ServiceAndRepeatNumTotal =
"";
19115 NumTrainsAtLoc = 0;
19117 NumPlatsAtThisLocCalculated =
false;
19120 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19122 PreviousService =
"";
19123 ServiceAndRepeatNumTotal =
"";
19124 NumTrainsAtLoc = 0;
19126 NumPlatsAtThisLocCalculated =
false;
19130 if(Ptr2 == LocServiceTimesVector.end())
19135 if(Ptr2 == LocServiceTimesVector.end())
19139 while(Ptr2->Location == Ptr1->Location)
19141 if(Ptr1->FrhMarker ==
"Frh")
19144 Ptr1->FrhMarker =
"FrhCounted";
19146 PreviousService =
"";
19147 NumTrainsAtLoc = 0;
19148 ServiceAndRepeatNumTotal =
"";
19149 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19153 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
19156 if(Ptr1->FrhMarker ==
"Frh")
19159 Ptr1->FrhMarker =
"FrhCounted";
19162 if(Ptr2 == LocServiceTimesVector.end())
19166 if(Ptr2->Location != Ptr1->Location)
19171 if(Ptr2 == LocServiceTimesVector.end())
19175 if(Ptr2->Location != Ptr1->Location)
19179 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
19181 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
19185 if(!NumPlatsAtThisLocCalculated)
19188 NumPlatsAtThisLocCalculated =
true;
19190 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19192 if(ServiceAndRepeatNumTotal ==
"")
19194 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
19195 NumTrainsAtLoc = 1;
19199 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
19202 PreviousService = Ptr2->ServiceAndRepeatNum;
19203 if(ServiceAndRepeatNumTotal ==
"")
19205 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
19206 NumTrainsAtLoc = 1;
19210 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
19213 if(Ptr1->FrhMarker ==
"Frh")
19216 Ptr1->FrhMarker =
"FrhCounted";
19219 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
19223 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
19225 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
19227 AnsiString Asterisk =
"";
19228 if(NumTrainsAtLoc > NumPlats)
19235 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19237 else if(FrhCount == 1)
19239 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19243 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19245 LastFrhCount = FrhCount;
19246 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
19247 AtLocsPrinted =
true;
19248 ServiceAndRepeatNumTotal =
"";
19251 if(Ptr2 == LocServiceTimesVector.end())
19255 if(Ptr2->Location != Ptr1->Location)
19260 if(Ptr2 == LocServiceTimesVector.end())
19268 TTFile3 <<
"Nothing to report for trains at locations";
19273 SequenceLog +=
"9\n";
19307 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
19312 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
19321 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19323 SingleServiceEntry = TDE;
19325 for(
unsigned int y = 0; y < SSAV.size(); y++)
19327 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
19329 SingleServiceVector.push_back(SingleServiceEntry);
19332 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
19334 PartServiceEntry = TDE;
19336 for(
unsigned int z = 0; z <= y; z++)
19341 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
19342 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
19345 PartServiceVector.push_back(PartServiceEntry);
19346 if(SSAV.at(y).Command ==
"fsp")
19348 SSAV.at(y).Command =
"Front split - original service continues below";
19349 SSAV.at(y).OtherHeadCode =
"";
19351 if(SSAV.at(y).Command ==
"rsp")
19353 SSAV.at(y).Command =
"Rear split - original service continues below";
19354 SSAV.at(y).OtherHeadCode =
"";
19358 else if(SSAV.at(y).Command ==
"Fns")
19360 SSAV.at(y).Command =
"chr-Fns";
19361 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19362 PartServiceVector.push_back(SingleServiceEntry);
19365 else if(SSAV.at(y).Command ==
"Fns-sh")
19367 SSAV.at(y).Command =
"chr-Fns-sh";
19368 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19369 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19370 PartServiceVector.push_back(SingleServiceEntry);
19373 else if(SSAV.at(y).Command ==
"F-nshs")
19375 SSAV.at(y).Command =
"chr-F-nshs";
19376 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19377 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19378 PartServiceVector.push_back(SingleServiceEntry);
19384 SequenceLog +=
"10\n";
19388 AnsiString NextRef;
19389 while(!PartServiceVector.empty())
19391 PartServiceEntry = PartServiceVector.at(0);
19392 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
19394 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
19396 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
19400 bool FinishType =
true, FoundFlag =
false;
19407 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
19411 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19415 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19421 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19422 SingleServiceVector.push_back(PartServiceVector.at(0));
19423 PartServiceVector.erase(PartServiceVector.begin());
19428 NewPartServiceEntry = PartServiceVector.at(0);
19432 PartServiceVector.push_back(NewPartServiceEntry);
19435 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
19440 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
19443 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19445 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
19448 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19450 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19453 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
19456 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19457 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19458 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19459 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19462 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
19466 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19467 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19468 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19476 SequenceLog += +
"11\n";
19477 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
19481 if(!PartServiceVector.empty())
19483 SequenceLog +=
"12\n";
19484 throw Exception(
"PartServiceVector should be empty here - size = " + AnsiString(PartServiceVector.size()));
19486 SequenceLog +=
"13\n";
19533 bool BufferFacingUnReportedFlag =
true;
19534 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19540 SequenceLog +=
"13a\n";
19541 throw Exception(
"Repeat entry present in SingleServiceVector at position " + AnsiString(x));
19544 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19546 bool BufferFlag =
false;
19547 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
19548 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
19549 AnsiString FrontLocName = AV.at(0).LocationName;
19550 int NextEntryPos, NextExitPos;
19553 if(ThisElement.
Conn[0] == RearTVPos)
19557 else if(ThisElement.
Conn[1] == RearTVPos)
19561 else if(ThisElement.
Conn[2] == RearTVPos)
19565 else if(ThisElement.
Conn[3] == RearTVPos)
19577 if(ThisElement.
Conn[ThisExitPos] == -1)
19579 SequenceLog =
"13b\n";
19580 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
19583 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
19584 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
19586 BufferFlag =
false;
19591 BufferFlag =
false;
19596 BufferFlag =
false;
19604 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
19606 ThisElement = NextElement;
19612 if(NextEntryPos == 0)
19616 else if(NextEntryPos == 1)
19620 else if(NextEntryPos == 2)
19624 else if(NextEntryPos == 3)
19629 ThisElement = NextElement;
19630 ThisExitPos = NextExitPos;
19635 if(BufferFacingUnReportedFlag)
19637 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
19638 BufferFacingUnReportedFlag =
false;
19640 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation\n";
19644 if(BufferFacingUnReportedFlag)
19646 TTFile3 <<
"Nothing to report for train facing directions\n\n";
19652 SequenceLog +=
"13c\n";
19655 AnsiString LocationNameToBeChecked =
"";
19656 bool MissingcdtUnreportedFlag =
true;
19658 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19661 unsigned int y = 0;
19662 int FirstInstance = 9999, SecondInstance = 9999;
19663 bool FullBreak =
false;
19664 MarkerList.clear();
19666 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
19675 LocationNameToBeChecked =
"";
19681 if(LocationNameToBeChecked ==
"")
19688 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
19691 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
19696 (AVEntry.
Command ==
"Frh-sh"))
19711 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
19713 AnsiString LocationName;
19720 int ExitLoc = TDEntry.
ActionVector.at(a).ExitList.front();
19725 LocationName = TDEntry.
ActionVector.at(a).LocationName;
19727 if(LocationName == LocationNameToBeChecked)
19729 SecondInstance = a;
19731 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
19733 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
19735 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
19738 if(MissingcdtUnreportedFlag)
19740 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
19742 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
19743 MarkerList.push_back(FirstInstance);
19744 MarkerList.push_back(SecondInstance);
19746 MissingcdtUnreportedFlag =
false;
19757 if(MissingcdtUnreportedFlag)
19759 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
19765 SequenceLog +=
"14\n";
19774 typedef std::list<AnsiString> TLocList;
19775 TLocList BackwardList, ForwardList;
19776 bool IntroLineNeeded =
true;
19777 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19779 unsigned int cdtPosition = 9999;
19780 AnsiString cdtLocation =
"";
19781 bool FoundSameName =
false;
19782 bool FerEntry =
false;
19783 MarkerList.clear();
19785 for(
unsigned int y = 0; y <= TDEntry.
ActionVector.size(); y++)
19792 BackwardList.clear();
19793 ForwardList.clear();
19794 bool ValidEnd =
false;
19800 (AVEntry.
Command ==
"Frh-sh"))
19805 if(FerEntry || ValidEnd)
19807 if(MarkerList.empty())
19814 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
19816 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
19818 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
19822 if(IntroLineNeeded)
19824 TTFile3 <<
"Questionable change of direction analysis.\n\n";
19825 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
19826 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
19827 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
19828 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
19829 IntroLineNeeded =
false;
19831 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
19846 for(
int z = y - 1; z >= 0; z--)
19849 if(AVEntry2.
Command ==
"cdt")
19853 AnsiString LocName =
"";
19863 if((LocName !=
"") && (AVEntry2.
LocationName != cdtLocation))
19865 BackwardList.push_back(LocName);
19868 BackwardList.sort();
19869 BackwardList.unique();
19870 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
19879 AnsiString LocName =
"";
19880 if(AVEntry3.
Command ==
"Fer")
19882 int ExitLoc = AVEntry3.
ExitList.front();
19890 if((LocName !=
"") && (AVEntry3.
LocationName != cdtLocation))
19892 ForwardList.push_back(LocName);
19895 ForwardList.sort();
19896 ForwardList.unique();
19897 FoundSameName =
false;
19899 if(!BackwardList.empty() && !ForwardList.empty())
19901 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
19903 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
19907 FoundSameName =
true;
19914 MarkerList.push_back(cdtPosition);
19919 if(IntroLineNeeded)
19921 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
19939 SequenceLog +=
"15\n";
19945 catch(
const Exception &e)
19947 AnsiString TTErrorFileName =
"Analysis Error.txt";
19948 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
19949 std::ofstream TTError(TTErrorFileName.c_str());
19952 ShowMessage(
"Analysis error file failed to open - can't be created");
19956 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
19957 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
19958 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
19961 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
19971 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
19973 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
19975 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
19977 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
19978 AnsiString Marker =
"";
19979 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
19982 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
19984 if(
int(x) == *MLIt)
20014 if(AVE.
Command.SubString(1,3) ==
"chr")
20023 AVE.
Command =
"Change of service to ";
20025 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
20027 AVE.
Command =
"Change to shuttle finishing service";
20029 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
20056 AnsiString ListOfExits =
"";
20065 VecFile << Marker <<
"Frh" <<
'\n';
20080 for(
unsigned int x = 0; x < Vector.size(); x++)
20083 if(Vector.at(x).ServiceReference == HeadCode)
20085 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
20087 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
20090 FinishType =
false;
20095 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
20098 FinishType =
false;
20103 return(Vector.at(x));
20107 return(Vector.at(Vector.size() - 1));
20116 if((Time1 ==
"") || (Time2 ==
""))
20121 int Mins = Time1.SubString(4,2).ToInt();
20122 int Hours = Time1.SubString(1,2).ToInt();
20123 int Time1Mins = (Hours * 60) + Mins;
20124 Mins = Time2.SubString(4,2).ToInt();
20125 Hours = Time2.SubString(1,2).ToInt();
20126 int Time2Mins = (Hours * 60) + Mins;
20127 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
20139 bool &AnalysisError,
int &MaxNumberOfSameDirections)
20146 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
20148 std::list<AnsiString> ServiceList;
20150 bool EvenComma =
false;
20151 for(
int x = 1; x <= Input.Length(); x++)
20153 TempStr1 = Input[x];
20154 if(TempStr1 == AnsiString(
',') && EvenComma)
20160 TempStr2 += Input[x];
20162 if(TempStr1 == AnsiString(
','))
20164 EvenComma = !EvenComma;
20168 while(TempStr2.Length() > 0)
20170 SCPos = TempStr2.Pos(
';');
20173 OneService = TempStr2.SubString(1, SCPos - 1);
20174 ServiceList.push_back(OneService);
20175 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
20179 ServiceList.push_back(TempStr2);
20183 ServiceList.sort();
20184 ServiceList.unique();
20185 NumTrainsAtLoc = ServiceList.size();
20188 int DirectionMarker = 0;
20190 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
20192 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20194 *SLIt = *SLIt +
"&0";
20196 SLIt3 = ServiceList.end();
20198 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
20199 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
20200 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
20202 MaxNumberOfSameDirections = 0;
20203 int SameDirectionCount = 0;
20205 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
20209 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
20215 CommaPos1 = SLIt1->Pos(
',');
20216 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
20218 SpacePos = ServiceRef1.Pos(
' ');
20222 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
20223 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
20224 if(RepeatInfo1[1] ==
'F')
20230 SpacePos = RepeatInfo1.Pos(
' ');
20231 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
20234 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
20236 AmpersandPos = AnsiTime1.Pos(
'&');
20237 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
20242 throw Exception(
"ASCLIt1 Error in " + Input);
20244 ServiceCallingLocsList1 = ASCLIt1->second;
20245 AmpersandPos = SLIt1->Pos(
'&');
20246 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
20247 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
20249 SameDirectionCount = 1;
20250 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
20252 CommaPos2 = SLIt2->Pos(
',');
20253 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
20255 SpacePos = ServiceRef2.Pos(
' ');
20259 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
20260 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
20261 if(RepeatInfo2[1] ==
'F')
20267 SpacePos = RepeatInfo2.Pos(
' ');
20268 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
20271 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
20273 AmpersandPos = AnsiTime2.Pos(
'&');
20274 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
20279 throw Exception(
"ASCLIt2 Error in " + Input);
20281 ServiceCallingLocsList2 = ASCLIt2->second;
20283 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
20285 int AmpersandPos = SLIt2->Pos(
'&');
20286 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
20287 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
20288 SameDirectionCount++;
20291 if(SameDirectionCount > MaxNumberOfSameDirections)
20293 MaxNumberOfSameDirections = SameDirectionCount;
20298 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
20301 AmpersandPos = SLIt3->Pos(
'&');
20302 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
20303 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
20306 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20309 AmpersandPos = SLIt->Pos(
'&');
20310 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
20311 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
20312 DirectionMarker = DirectionMarkerString.ToInt();
20313 AnsiString DirectionSuffix =
"";
20315 if(DirectionMarker < 27)
20317 c = 64 + DirectionMarker;
20318 DirectionSuffix =
"," + AnsiString(c);
20320 else if(DirectionMarker < 53)
20322 c = 65 + DirectionMarker - 27;
20323 DirectionSuffix =
",A" + AnsiString(c);
20327 DirectionSuffix =
",?";
20329 *SLIt = ServiceWithoutMarker + DirectionSuffix;
20332 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20334 Output = Output + *SLIt +
",";
20336 if(Output.Length() > 0)
20338 Output = Output.SubString(1, Output.Length() - 1);
20344 catch(
const Exception &e)
20346 AnalysisError =
true;
20358 AnsiString InternalInput = Input, Output =
"", OneService =
"";
20360 std::list<AnsiString> ServiceList;
20362 while(InternalInput.Length() > 0)
20364 CommaPos = InternalInput.Pos(
',');
20367 OneService = InternalInput.SubString(1, CommaPos - 1);
20368 ServiceList.push_back(OneService);
20369 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
20373 ServiceList.push_back(InternalInput);
20374 InternalInput =
"";
20378 ServiceList.sort();
20379 ServiceList.unique();
20380 NumTrainsAtLoc = ServiceList.size();
20381 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20383 Output = Output + *SLIt +
",";
20385 if(Output.Length() > 0)
20387 Output = Output.SubString(1, Output.Length() - 1);
20400 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
20402 std::list<AnsiString>::iterator LP1, LP2, ListPtr1, ListPtr2, LocPtr1, LocPtr2;
20407 bool LocFound =
false;
20408 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
20410 TDateTime FirstServiceTime;
20413 int Ref1Target = 0, Ref1Count = 0;
20414 int Ref2Target = 0, Ref2Count = 0;
20432 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
20435 if((*ListPtr1) == Location)
20437 LocPtr1 = ListPtr1;
20440 if(ListPtr1->SubString(1, 3) ==
"%%%")
20442 AnsiString CDTTime = ListPtr1->SubString(4, 5);
20447 FirstServiceTime = TDateTime(-1);
20448 bool BreakFlag =
false;
20451 if(TDVIt->ServiceReference == Ref1)
20453 if(Ref1Target > Ref1Count)
20458 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20459 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20463 FirstServiceTime = AVIt->EventTime;
20469 FirstServiceTime = AVIt->ArrivalTime;
20475 FirstServiceTime = AVIt->DepartureTime;
20486 if(IncMinutes == -1)
20488 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20490 if(FirstServiceTime == TDateTime(-1))
20492 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20496 if(!Arrival && (Time1 == CDTTime))
20501 if(Arrival && (Time1 == CDTTime))
20505 if(Time1 > CDTTime)
20510 if(Time1 < CDTTime)
20523 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
20525 if((*ListPtr2) == Location)
20527 LocPtr2 = ListPtr2;
20530 if(ListPtr2->SubString(1, 3) ==
"%%%")
20532 AnsiString CDTTime = ListPtr2->SubString(4, 5);
20537 FirstServiceTime = TDateTime(-1);
20538 bool BreakFlag =
false;
20541 if(TDVIt->ServiceReference == Ref2)
20543 if(Ref2Target > Ref2Count)
20548 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20549 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20553 FirstServiceTime = AVIt->EventTime;
20559 FirstServiceTime = AVIt->ArrivalTime;
20565 FirstServiceTime = AVIt->DepartureTime;
20576 if(IncMinutes == -1)
20578 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20580 if(FirstServiceTime == TDateTime(-1))
20582 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20586 if(!Arrival && (Time2 == CDTTime))
20591 if(Arrival && (Time2 == CDTTime))
20595 if(Time2 > CDTTime)
20600 if(Time2 < CDTTime)
20615 LP1 = List1.begin();
20617 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
20619 if(ListPtr1 == List1.begin())
20623 if(ListPtr1->SubString(1, 3) ==
"%%%")
20630 LP2 = List2.begin();
20632 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
20634 if(ListPtr2 == List2.begin())
20638 if(ListPtr2->SubString(1, 3) ==
"%%%")
20648 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20650 if(ListPtr1 == LocPtr1)
20654 if(ListPtr1->SubString(1, 3) ==
"%%%")
20658 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20660 if(ListPtr2 == LocPtr2)
20664 if(ListPtr2->SubString(1, 3) ==
"%%%")
20668 if((*ListPtr1) == (*ListPtr2))
20685 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20687 if(ListPtr1 == List1.end())
20691 if(ListPtr1->SubString(1, 3) ==
"%%%")
20695 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20697 if(ListPtr2 == List2.end())
20701 if(ListPtr2->SubString(1, 3) ==
"%%%")
20705 if((*ListPtr1) == (*ListPtr2))
20722 if(ExitList.empty())
20728 AnsiString ExitLocList =
"";
20731 unsigned int Counter = 0;
20732 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
20736 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
20738 ExitLocList +=
"\n";
20741 if(StartName ==
"")
20743 if(ExitList.size() == 1)
20747 return(
" at " + ID);
20752 if(ExitList.size() < 4)
20754 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20759 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
20764 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
20769 if(ExitList.size() < 4)
20771 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20776 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
20782 if(ExitList.size() < 4)
20784 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20785 return(
" at " + StartName);
20789 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
20790 return(
" at " + StartName);
20830 AnsiString FormatStr =
"####0.0";
20831 AnsiString AvLateArrMins =
"";
20832 AnsiString AvEarlyArrMins =
"";
20833 AnsiString AvLatePassMins =
"";
20834 AnsiString AvEarlyPassMins =
"";
20835 AnsiString AvLateDepMins =
"";
20836 AnsiString AvLateExitMins =
"";
20837 AnsiString AvEarlyExitMins =
"";
20840 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
20873 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
20874 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
20886 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
20890 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
20898 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
20902 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
20910 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
20918 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
20922 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
20926 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
20930 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
20934 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
20938 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
20943 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
20947 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
20951 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
20955 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
20959 PerfFile <<
LateExits <<
" late exits" <<
'\n';
20963 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
20967 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
20971 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
20976 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
20980 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
20984 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
20988 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
20992 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
20994 TDateTime TempExcessLCDownTime;
21008 if(TempExcessLCDownTime > TDateTime(0))
21014 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
21018 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
21030 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
21034 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
21070 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
21074 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
21080 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
21084 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
21087 AnsiString AvLateMinsLocsNotReached =
"";
21093 if(LocsNotReached > 0)
21096 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
21100 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
21104 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
21116 PerfFile <<
Derailments <<
" derailments" <<
'\n';
21120 PerfFile <<
Derailments <<
" derailment" <<
'\n';
21130 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
21132 bool DerailSPADFlag =
false, CrashFlag =
false;
21134 int OverallScorePercent = 100;
21135 int TotArrDepExit = 0;
21136 double TotLateMinsFactor = 1;
21137 double MissedStopAndSPADRiskFactor = 1;
21138 double NetNegFactor = 1;
21148 OverallScorePercent = 5;
21149 DerailSPADFlag =
true;
21153 OverallScorePercent = 0;
21156 if(OverallScorePercent == 100)
21161 LatenessPenalty = 0;
21167 if(TotArrDepExit > 0)
21176 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
21178 OverallScorePercent = 100 * NetNegFactor;
21181 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
21184 AnsiString OneFailureString =
", though the failure would account for some poor performance";
21185 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
21186 AnsiString AddedString =
"";
21189 AddedString = OneFailureString;
21193 AddedString = TwoOrMoreFailureString;
21195 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
21196 AnsiString Rating =
"";
21197 if(OverallScorePercent == 100)
21199 Rating =
"Perfect!";
21201 else if(OverallScorePercent >= 95)
21203 Rating =
"Excellent";
21205 else if(OverallScorePercent >= 90)
21207 Rating =
"Very good";
21209 else if(OverallScorePercent >= 80)
21213 else if(OverallScorePercent >= 70)
21217 else if(OverallScorePercent >= 60)
21219 Rating =
"Unacceptable" + AddedString;
21221 else if(OverallScorePercent >= 50)
21223 Rating =
"Poor" + AddedString;
21225 else if(OverallScorePercent >= 40)
21227 Rating =
"Bad" + AddedString;
21229 else if(OverallScorePercent >= 30)
21231 Rating =
"Very bad" + AddedString;
21233 else if(OverallScorePercent >= 20)
21235 Rating =
"Terrible" + AddedString;
21237 else if(OverallScorePercent >= 10)
21239 Rating =
"Appalling" + AddedString;
21241 else if(OverallScorePercent >= 5)
21245 Rating =
"Disastrous - potential loss of life";
21250 Rating =
"Dire" + AddedString;
21253 else if(OverallScorePercent < 5)
21257 Rating =
"Catastrophic - loss of life";
21261 Rating =
"Abysmal";
21264 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
21268 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
21270 PerfFile <<
'\n' <<
"***************************************";
21280 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21330 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21365 int IncrementalMinutes = 0;
21379 bool TrainOperatingFlag =
false;
21384 TrainOperatingFlag =
true;
21388 if(TrainOperatingFlag)
21396 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
21443 AnsiString HeadCode;
21447 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21451 HCandTrainPosParam.first = HeadCode;
21452 HCandTrainPosParam.second = TrainID;
21454 if((TimeToAct >= 0) && (TimeToAct < 59.9))
21457 OpTimeToActMultiMapEntry.first = TimeToAct;
21458 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21487 float TimeToAct = 0;
21488 int DistanceToRedSignal = 0;
21491 ContinuationEntryVecPosVector.clear();
21492 bool LaterTrain =
false;
21496 LaterTrain =
false;
21497 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
21508 if(!ContinuationEntryVecPosVector.empty())
21510 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
21512 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
21526 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
21527 AnsiString HeadCode = CTEIt->second.HeadCode;
21528 float CurrentStopTime;
21529 float LaterStopTime;
21530 float RecoverableTime;
21533 int DistanceToExit;
21535 bool SigControlAndCanPassRedSignal =
false;
21543 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
21549 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
21550 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
21553 if(AvTrackSpeed < 30)
21557 if(DistanceToRedSignal == -1)
21563 int Speed = AvTrackSpeed;
21564 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
21565 if(AvTrackSpeed > MaxSpeed)
21569 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
21572 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
21575 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
21580 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
21581 TimeToAct += MinsBefEnter;
21584 HCandTrainPosParam.first = HeadCode;
21585 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
21588 if(TimeToAct < 59.9)
21590 OpTimeToActMultiMapEntry.first = TimeToAct;
21591 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21616 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21626 TimeToExitMultiMapEntry.first = ExitPair;
21627 TimeToExitMultiMapEntry.second = ExitInfo;
21637 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
21638 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
21647 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
21648 int DistanceToRedSignal = 0;
21649 DistanceToExit = -1;
21650 ExitPair.first = -1;
21651 ExitPair.second = -1;
21652 int CumTrackSpeed = 0;
21654 int TrackSpeedCount = 0;
21655 float KmPerLocationStop;
21656 float MaxAllowableSpeed;
21666 int CurrentElement = TrackVectorPosition;
21667 int CurrentEntryPos = TrackVectorPositionEntryPos;
21672 CurrentStopTime = 0;
21674 RecoverableTime = 0;
21675 if(CurrentElement == -1)
21680 int CurrentExitPos;
21685 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
21689 CurrentExitPos = 1;
21693 CurrentExitPos = 3;
21698 CurrentExitPos = 0;
21737 TimeToDepart+= 0.5;
21739 if(TimeToDepart < 0.5)
21741 TimeToDepart = 0.5;
21744 CurrentStopTime = float(TimeToDepart);
21752 CurrentStopTime = float(TimeToDepart);
21763 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
21774 else if(SigControlAndCanPassRedSignal)
21779 if((NextEntryPos == 0) || (NextEntryPos == 2))
21800 CurrentElement = NextElement;
21801 CurrentEntryPos = NextEntryPos;
21802 CurrentExitPos = NextExitPos;
21814 int LaterStopNumber = 0;
21818 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
21827 if(CurrentEntryPos > 1)
21842 DistanceToExit = DistanceToRedSignal;
21847 if(TrackSpeedCount > 0)
21849 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
21853 if(CurrentEntryPos > 1)
21864 if(LaterStopNumber > 0)
21866 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
21867 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
21873 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
21877 if(AvTrackSpeed > MaxAllowableSpeed)
21879 AvTrackSpeed = MaxAllowableSpeed;
21891 bool StopRequired =
false;
21910 int TrainOnElement;
21917 if(CurrentEntryPos > 1)
21926 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
21935 double StopTimeDouble;
21948 if(StopTimeDouble < 0.5)
21950 StopTimeDouble = 0.5;
21954 LaterStopTime += float(StopTimeDouble);
21955 RecoverableTime += StopTimeDouble - 0.5;
21956 if((LaterStopNumber == 1) && (TrainID > -1))
21964 if((AVPtr + 1)->FormatType ==
TimeLoc)
21968 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
21979 if(StopTimeDouble < 0.5)
21981 StopTimeDouble = 0.5;
21984 LaterStopTime += float(StopTimeDouble);
21985 RecoverableTime += StopTimeDouble - 0.5;
21986 if((LaterStopNumber == 1) && (TrainID > -1))
21996 StopTimeDouble = double((AVPtr + 2)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22007 if(StopTimeDouble < 0.5)
22009 StopTimeDouble = 0.5;
22012 LaterStopTime += float(StopTimeDouble);
22013 RecoverableTime += StopTimeDouble - 0.5;
22014 if((LaterStopNumber == 1) && (TrainID > -1))
22031 if(NextElement == -1)
22040 if((NextEntryPos == 0) || (NextEntryPos == 2))
22061 CurrentElement = NextElement;
22062 CurrentEntryPos = NextEntryPos;
22063 CurrentExitPos = NextExitPos;
22068 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22081 if(TrackSpeedCount > 0)
22083 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22087 if(CurrentEntryPos > 1)
22098 if(LaterStopNumber > 0)
22100 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22101 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22107 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22111 if(AvTrackSpeed > MaxAllowableSpeed)
22113 AvTrackSpeed = MaxAllowableSpeed;
22116 return(DistanceToRedSignal);